xref: /petsc/src/mat/utils/gcreate.c (revision 2920cce0f08e88ce102428b9df84f61867de9dc8)
1af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h"  I*/
27807a1faSBarry Smith 
3d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatSetBlockSizes_Default(Mat mat, PetscInt rbs, PetscInt cbs)
4d71ae5a4SJacob Faibussowitsch {
546533700Sstefano_zampini   PetscFunctionBegin;
63ba16761SJacob Faibussowitsch   if (!mat->preallocated) PetscFunctionReturn(PETSC_SUCCESS);
7aed4548fSBarry Smith   PetscCheck(mat->rmap->bs <= 0 || mat->rmap->bs == rbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot change row block size %" PetscInt_FMT " to %" PetscInt_FMT, mat->rmap->bs, rbs);
8aed4548fSBarry Smith   PetscCheck(mat->cmap->bs <= 0 || mat->cmap->bs == cbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot change column block size %" PetscInt_FMT " to %" PetscInt_FMT, mat->cmap->bs, cbs);
93ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1046533700Sstefano_zampini }
1146533700Sstefano_zampini 
12d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatShift_Basic(Mat Y, PetscScalar a)
13d71ae5a4SJacob Faibussowitsch {
147d68702bSBarry Smith   PetscInt    i, start, end;
157d68702bSBarry Smith   PetscScalar alpha = a;
167d68702bSBarry Smith   PetscBool   prevoption;
177d68702bSBarry Smith 
187d68702bSBarry Smith   PetscFunctionBegin;
199566063dSJacob Faibussowitsch   PetscCall(MatGetOption(Y, MAT_NO_OFF_PROC_ENTRIES, &prevoption));
209566063dSJacob Faibussowitsch   PetscCall(MatSetOption(Y, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
219566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(Y, &start, &end));
227d68702bSBarry Smith   for (i = start; i < end; i++) {
2348a46eb9SPierre Jolivet     if (i < Y->cmap->N) PetscCall(MatSetValues(Y, 1, &i, 1, &i, &alpha, ADD_VALUES));
24ab6153dcSStefano Zampini   }
259566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(Y, MAT_FINAL_ASSEMBLY));
269566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(Y, MAT_FINAL_ASSEMBLY));
279566063dSJacob Faibussowitsch   PetscCall(MatSetOption(Y, MAT_NO_OFF_PROC_ENTRIES, prevoption));
283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
297d68702bSBarry Smith }
307d68702bSBarry Smith 
3105869f15SSatish Balay /*@
3269dd0797SLois Curfman McInnes   MatCreate - Creates a matrix where the type is determined
3311a5261eSBarry Smith   from either a call to `MatSetType()` or from the options database
34*2920cce0SJacob Faibussowitsch   with a call to `MatSetFromOptions()`.
3583e1b59cSLois Curfman McInnes 
36d083f849SBarry Smith   Collective
37cb13003dSBarry Smith 
38f69a0ea3SMatthew Knepley   Input Parameter:
39f69a0ea3SMatthew Knepley . comm - MPI communicator
407807a1faSBarry Smith 
417807a1faSBarry Smith   Output Parameter:
42dc401e71SLois Curfman McInnes . A - the matrix
43e0b365e2SLois Curfman McInnes 
44273d9f13SBarry Smith   Options Database Keys:
4511a5261eSBarry Smith + -mat_type seqaij   - `MATSEQAIJ` type, uses `MatCreateSeqAIJ()`
4611a5261eSBarry Smith . -mat_type mpiaij   - `MATMPIAIJ` type, uses `MatCreateAIJ()`
4711a5261eSBarry Smith . -mat_type seqdense - `MATSEQDENSE`, uses `MatCreateSeqDense()`
4811a5261eSBarry Smith . -mat_type mpidense - `MATMPIDENSE` type, uses `MatCreateDense()`
4911a5261eSBarry Smith . -mat_type seqbaij  - `MATSEQBAIJ` type, uses `MatCreateSeqBAIJ()`
5011a5261eSBarry Smith - -mat_type mpibaij  - `MATMPIBAIJ` type, uses `MatCreateBAIJ()`
51e0b365e2SLois Curfman McInnes 
522ef1f0ffSBarry Smith    See the manpages for particular formats (e.g., `MATSEQAIJ`)
5383e1b59cSLois Curfman McInnes    for additional format-specific options.
54e0b365e2SLois Curfman McInnes 
55273d9f13SBarry Smith   Level: beginner
56273d9f13SBarry Smith 
57*2920cce0SJacob Faibussowitsch   Notes:
58*2920cce0SJacob Faibussowitsch   The default matrix type is `MATAIJ`, using the routines `MatCreateSeqAIJ()` or
59*2920cce0SJacob Faibussowitsch   `MatCreateAIJ()` if you do not set a type in the options database. If you never call
60*2920cce0SJacob Faibussowitsch   `MatSetType()` or `MatSetFromOptions()` it will generate an error when you try to use the
61*2920cce0SJacob Faibussowitsch   matrix.
62*2920cce0SJacob Faibussowitsch 
631cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
64db781477SPatrick Sanan           `MatCreateSeqDense()`, `MatCreateDense()`,
65db781477SPatrick Sanan           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
66db781477SPatrick Sanan           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
67db781477SPatrick Sanan           `MatConvert()`
68273d9f13SBarry Smith @*/
69d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate(MPI_Comm comm, Mat *A)
70d71ae5a4SJacob Faibussowitsch {
71273d9f13SBarry Smith   Mat B;
72273d9f13SBarry Smith 
73273d9f13SBarry Smith   PetscFunctionBegin;
74f69a0ea3SMatthew Knepley   PetscValidPointer(A, 2);
7597f1f81fSBarry Smith 
760298fd71SBarry Smith   *A = NULL;
779566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
788ba1e511SMatthew Knepley 
799566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(B, MAT_CLASSID, "Mat", "Matrix", "Mat", comm, MatDestroy, MatView));
809566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->rmap));
819566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->cmap));
829566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(VECSTANDARD, &B->defaultvectype));
833faff063SStefano Zampini   PetscCall(PetscStrallocpy(PETSCRANDER48, &B->defaultrandtype));
8426fbe8dcSKarl Rupp 
85b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_UNKNOWN;
86b94d7dedSBarry Smith   B->hermitian                   = PETSC_BOOL3_UNKNOWN;
87b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_UNKNOWN;
88b94d7dedSBarry Smith   B->spd                         = PETSC_BOOL3_UNKNOWN;
89b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_FALSE;
90b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_FALSE;
91b94d7dedSBarry Smith 
9294342113SStefano Zampini   B->congruentlayouts = PETSC_DECIDE;
93273d9f13SBarry Smith   B->preallocated     = PETSC_FALSE;
946f3d89d0SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
956f3d89d0SStefano Zampini   B->boundtocpu = PETSC_TRUE;
966f3d89d0SStefano Zampini #endif
97273d9f13SBarry Smith   *A = B;
983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99273d9f13SBarry Smith }
100273d9f13SBarry Smith 
101422a814eSBarry Smith /*@
10211a5261eSBarry Smith   MatSetErrorIfFailure - Causes `Mat` to generate an immediate error, for example a zero pivot, is detected.
103422a814eSBarry Smith 
104c3339decSBarry Smith   Logically Collective
105422a814eSBarry Smith 
106422a814eSBarry Smith   Input Parameters:
10711a5261eSBarry Smith + mat - matrix obtained from `MatCreate()`
10811a5261eSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated
109422a814eSBarry Smith 
110422a814eSBarry Smith   Level: advanced
111422a814eSBarry Smith 
11211a5261eSBarry Smith   Note:
11311a5261eSBarry 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
11411a5261eSBarry Smith   or result in a `KSPConvergedReason` indicating the method did not converge.
11511a5261eSBarry Smith 
1161cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `PCSetErrorIfFailure()`, `KSPConvergedReason`, `SNESConvergedReason`
117422a814eSBarry Smith @*/
118d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetErrorIfFailure(Mat mat, PetscBool flg)
119d71ae5a4SJacob Faibussowitsch {
120422a814eSBarry Smith   PetscFunctionBegin;
121422a814eSBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
122422a814eSBarry Smith   PetscValidLogicalCollectiveBool(mat, flg, 2);
12384d44b13SHong Zhang   mat->erroriffailure = flg;
1243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
125422a814eSBarry Smith }
126422a814eSBarry Smith 
127f69a0ea3SMatthew Knepley /*@
128f69a0ea3SMatthew Knepley   MatSetSizes - Sets the local and global sizes, and checks to determine compatibility
129f69a0ea3SMatthew Knepley 
130c3339decSBarry Smith   Collective
131f69a0ea3SMatthew Knepley 
132f69a0ea3SMatthew Knepley   Input Parameters:
133f69a0ea3SMatthew Knepley + A - the matrix
13411a5261eSBarry Smith . m - number of local rows (or `PETSC_DECIDE`)
13511a5261eSBarry Smith . n - number of local columns (or `PETSC_DECIDE`)
13611a5261eSBarry Smith . M - number of global rows (or `PETSC_DETERMINE`)
13711a5261eSBarry Smith - N - number of global columns (or `PETSC_DETERMINE`)
138f69a0ea3SMatthew Knepley 
1392fe279fdSBarry Smith   Level: beginner
1402fe279fdSBarry Smith 
141f69a0ea3SMatthew Knepley   Notes:
1422ef1f0ffSBarry Smith   `m` (`n`) and `M` (`N`) cannot be both `PETSC_DECIDE`
1432ef1f0ffSBarry Smith   If one processor calls this with `M` (`N`) of `PETSC_DECIDE` then all processors must, otherwise the program will hang.
144f69a0ea3SMatthew Knepley 
14511a5261eSBarry Smith   If `PETSC_DECIDE` is not used for the arguments 'm' and 'n', then the
146f69a0ea3SMatthew Knepley   user must ensure that they are chosen to be compatible with the
147f69a0ea3SMatthew Knepley   vectors. To do this, one first considers the matrix-vector product
1482ef1f0ffSBarry Smith   'y = A x'. The `m` that is used in the above routine must match the
1492ef1f0ffSBarry Smith   local size used in the vector creation routine `VecCreateMPI()` for 'y'.
1502ef1f0ffSBarry Smith   Likewise, the `n` used must match that used as the local size in
15111a5261eSBarry Smith   `VecCreateMPI()` for 'x'.
152f69a0ea3SMatthew Knepley 
153f73d5cc4SBarry Smith   You cannot change the sizes once they have been set.
154f73d5cc4SBarry Smith 
15511a5261eSBarry Smith   The sizes must be set before `MatSetUp()` or MatXXXSetPreallocation() is called.
156f73d5cc4SBarry Smith 
1571cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatGetSize()`, `PetscSplitOwnership()`
158f69a0ea3SMatthew Knepley @*/
159d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
160d71ae5a4SJacob Faibussowitsch {
161f69a0ea3SMatthew Knepley   PetscFunctionBegin;
1620700a824SBarry Smith   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
163a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, M, 4);
164a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, N, 5);
165aed4548fSBarry 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);
166aed4548fSBarry 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);
1679371c9d4SSatish 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,
1689371c9d4SSatish Balay              A->rmap->n, A->rmap->N);
1699371c9d4SSatish 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,
1709371c9d4SSatish Balay              A->cmap->n, A->cmap->N);
171d0f46423SBarry Smith   A->rmap->n = m;
172d0f46423SBarry Smith   A->cmap->n = n;
17359cb773eSBarry Smith   A->rmap->N = M > -1 ? M : A->rmap->N;
17459cb773eSBarry Smith   A->cmap->N = N > -1 ? N : A->cmap->N;
1753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
176f69a0ea3SMatthew Knepley }
177f69a0ea3SMatthew Knepley 
17805869f15SSatish Balay /*@
179273d9f13SBarry Smith   MatSetFromOptions - Creates a matrix where the type is determined
180*2920cce0SJacob Faibussowitsch   from the options database.
181273d9f13SBarry Smith 
182c3339decSBarry Smith   Collective
183273d9f13SBarry Smith 
184273d9f13SBarry Smith   Input Parameter:
185fe59aa6dSJacob Faibussowitsch . B - the matrix
186273d9f13SBarry Smith 
187273d9f13SBarry Smith   Options Database Keys:
18811a5261eSBarry Smith + -mat_type seqaij   - `MATSEQAIJ` type, uses `MatCreateSeqAIJ()`
18911a5261eSBarry Smith . -mat_type mpiaij   - `MATMPIAIJ` type, uses `MatCreateAIJ()`
19011a5261eSBarry Smith . -mat_type seqdense - `MATSEQDENSE` type, uses `MatCreateSeqDense()`
19111a5261eSBarry Smith . -mat_type mpidense - `MATMPIDENSE`, uses `MatCreateDense()`
19211a5261eSBarry Smith . -mat_type seqbaij  - `MATSEQBAIJ`, uses `MatCreateSeqBAIJ()`
19311a5261eSBarry Smith - -mat_type mpibaij  - `MATMPIBAIJ`, uses `MatCreateBAIJ()`
194273d9f13SBarry Smith 
1952ef1f0ffSBarry Smith    See the manpages for particular formats (e.g., `MATSEQAIJ`)
196273d9f13SBarry Smith    for additional format-specific options.
197bd9ce289SLois Curfman McInnes 
1981d69843bSLois Curfman McInnes   Level: beginner
1991d69843bSLois Curfman McInnes 
200*2920cce0SJacob Faibussowitsch   Notes:
201*2920cce0SJacob Faibussowitsch   Generates a parallel MPI matrix if the communicator has more than one processor.  The default
202*2920cce0SJacob Faibussowitsch   matrix type is `MATAIJ`, using the routines `MatCreateSeqAIJ()` and `MatCreateAIJ()` if you
203*2920cce0SJacob Faibussowitsch   do not select a type in the options database.
204*2920cce0SJacob Faibussowitsch 
2051cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
206db781477SPatrick Sanan           `MatCreateSeqDense()`, `MatCreateDense()`,
207db781477SPatrick Sanan           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
208db781477SPatrick Sanan           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
209db781477SPatrick Sanan           `MatConvert()`
2107807a1faSBarry Smith @*/
211d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetFromOptions(Mat B)
212d71ae5a4SJacob Faibussowitsch {
213f3be49caSLisandro Dalcin   const char *deft = MATAIJ;
214f3be49caSLisandro Dalcin   char        type[256];
21569df5c0cSJed Brown   PetscBool   flg, set;
21616e04d98SRichard Tran Mills   PetscInt    bind_below = 0;
217dbb450caSBarry Smith 
2183a40ed3dSBarry Smith   PetscFunctionBegin;
2190700a824SBarry Smith   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
220f3be49caSLisandro Dalcin 
221d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)B);
222535b19f3SBarry Smith 
223535b19f3SBarry Smith   if (B->rmap->bs < 0) {
224535b19f3SBarry Smith     PetscInt newbs = -1;
2259566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-mat_block_size", "Set the blocksize used to store the matrix", "MatSetBlockSize", newbs, &newbs, &flg));
226535b19f3SBarry Smith     if (flg) {
2279566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->rmap, newbs));
2289566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->cmap, newbs));
229535b19f3SBarry Smith     }
230535b19f3SBarry Smith   }
231535b19f3SBarry Smith 
2329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-mat_type", "Matrix type", "MatSetType", MatList, deft, type, 256, &flg));
233273d9f13SBarry Smith   if (flg) {
2349566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, type));
235f3be49caSLisandro Dalcin   } else if (!((PetscObject)B)->type_name) {
2369566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, deft));
237273d9f13SBarry Smith   }
238f3be49caSLisandro Dalcin 
2399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", &B->checksymmetryonassembly));
2409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", B->checksymmetrytol, &B->checksymmetrytol, NULL));
2419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_null_space_test", "Checks if provided null space is correct in MatAssemblyEnd()", "MatSetNullSpaceTest", B->checknullspaceonassembly, &B->checknullspaceonassembly, NULL));
2429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_error_if_failure", "Generate an error if an error occurs when factoring the matrix", "MatSetErrorIfFailure", B->erroriffailure, &B->erroriffailure, NULL));
243840d65ccSBarry Smith 
244dbbe0bcdSBarry Smith   PetscTryTypeMethod(B, setfromoptions, PetscOptionsObject);
245f3be49caSLisandro Dalcin 
24669df5c0cSJed Brown   flg = PETSC_FALSE;
2479566063dSJacob 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));
2489566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, flg));
24969df5c0cSJed Brown   flg = PETSC_FALSE;
2509566063dSJacob 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));
2519566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, flg));
252478db826SMatthew G. Knepley   flg = PETSC_FALSE;
2539566063dSJacob 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));
2549566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_IGNORE_ZERO_ENTRIES, flg));
25569df5c0cSJed Brown 
2561a2c6b5cSJunchao Zhang   flg = PETSC_FALSE;
2579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_form_explicit_transpose", "Hint to form an explicit transpose for operations like MatMultTranspose", "MatSetOption", flg, &flg, &set));
2589566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_FORM_EXPLICIT_TRANSPOSE, flg));
2591a2c6b5cSJunchao Zhang 
26016e04d98SRichard Tran Mills   /* Bind to CPU if below a user-specified size threshold.
26116e04d98SRichard Tran Mills    * This perhaps belongs in the options for the GPU Mat types, but MatBindToCPU() does nothing when called on non-GPU types,
26216e04d98SRichard Tran Mills    * and putting it here makes is more maintainable than duplicating this for all. */
2639566063dSJacob 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));
26448a46eb9SPierre Jolivet   if (flg && B->rmap->n < bind_below) PetscCall(MatBindToCPU(B, PETSC_TRUE));
26516e04d98SRichard Tran Mills 
2665d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
267dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)B, PetscOptionsObject));
268d0609cedSBarry Smith   PetscOptionsEnd();
2693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2707807a1faSBarry Smith }
2717807a1faSBarry Smith 
272987010e7SBarry Smith /*@C
27311a5261eSBarry Smith   MatXAIJSetPreallocation - set preallocation for serial and parallel `MATAIJ`, `MATBAIJ`, and `MATSBAIJ` matrices and their unassembled versions.
27463562e91SJed Brown 
275c3339decSBarry Smith   Collective
27663562e91SJed Brown 
2774165533cSJose E. Roman   Input Parameters:
27863562e91SJed Brown + A     - matrix being preallocated
27963562e91SJed Brown . bs    - block size
28041319c1dSStefano Zampini . dnnz  - number of nonzero column blocks per block row of diagonal part of parallel matrix
28141319c1dSStefano Zampini . onnz  - number of nonzero column blocks per block row of off-diagonal part of parallel matrix
28241319c1dSStefano Zampini . dnnzu - number of nonzero column blocks per block row of upper-triangular part of diagonal part of parallel matrix
28341319c1dSStefano Zampini - onnzu - number of nonzero column blocks per block row of upper-triangular part of off-diagonal part of parallel matrix
28463562e91SJed Brown 
28563562e91SJed Brown   Level: beginner
28663562e91SJed Brown 
2871cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`,
2882fe279fdSBarry Smith           `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`,
289db781477SPatrick Sanan           `PetscSplitOwnership()`
29063562e91SJed Brown @*/
291d71ae5a4SJacob Faibussowitsch PetscErrorCode MatXAIJSetPreallocation(Mat A, PetscInt bs, const PetscInt dnnz[], const PetscInt onnz[], const PetscInt dnnzu[], const PetscInt onnzu[])
292d71ae5a4SJacob Faibussowitsch {
29341319c1dSStefano Zampini   PetscInt cbs;
29463562e91SJed Brown   void (*aij)(void);
295e8bd9bafSStefano Zampini   void (*is)(void);
296990279feSStefano Zampini   void (*hyp)(void) = NULL;
29763562e91SJed Brown 
29863562e91SJed Brown   PetscFunctionBegin;
29941319c1dSStefano Zampini   if (bs != PETSC_DECIDE) { /* don't mess with an already set block size */
3009566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(A, bs));
30141319c1dSStefano Zampini   }
3029566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
3039566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
3049566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSizes(A, &bs, &cbs));
30541319c1dSStefano Zampini   /* these routines assumes bs == cbs, this should be checked somehow */
3069566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(A, bs, 0, dnnz));
3079566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(A, bs, 0, dnnz, 0, onnz));
3089566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(A, bs, 0, dnnzu));
3099566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(A, bs, 0, dnnzu, 0, onnzu));
31063562e91SJed Brown   /*
311e8bd9bafSStefano 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
31263562e91SJed Brown     good before going on with it.
31363562e91SJed Brown   */
3149566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIAIJSetPreallocation_C", &aij));
3159566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatISSetPreallocation_C", &is));
316990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3179566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatHYPRESetPreallocation_C", &hyp));
318990279feSStefano Zampini #endif
31948a46eb9SPierre Jolivet   if (!aij && !is && !hyp) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", &aij));
320990279feSStefano Zampini   if (aij || is || hyp) {
32141319c1dSStefano Zampini     if (bs == cbs && bs == 1) {
3229566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz));
3239566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz, 0, onnz));
3249566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz, 0, onnz));
325990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3269566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz, 0, onnz));
327990279feSStefano Zampini #endif
3283e5f4774SJed Brown     } else { /* Convert block-row precallocation to scalar-row */
32963562e91SJed Brown       PetscInt i, m, *sdnnz, *sonnz;
3309566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(A, &m, NULL));
3319566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2((!!dnnz) * m, &sdnnz, (!!onnz) * m, &sonnz));
332dec54756SJed Brown       for (i = 0; i < m; i++) {
33341319c1dSStefano Zampini         if (dnnz) sdnnz[i] = dnnz[i / bs] * cbs;
33441319c1dSStefano Zampini         if (onnz) sonnz[i] = onnz[i / bs] * cbs;
33563562e91SJed Brown       }
3369566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL));
3379566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
3389566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
339990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3409566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
341990279feSStefano Zampini #endif
3429566063dSJacob Faibussowitsch       PetscCall(PetscFree2(sdnnz, sonnz));
34363562e91SJed Brown     }
34463562e91SJed Brown   }
3453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34663562e91SJed Brown }
34763562e91SJed Brown 
348273d9f13SBarry Smith /*
349eb6b5d47SBarry Smith         Merges some information from Cs header to A; the C object is then destroyed
350d0f46423SBarry Smith 
351d0f46423SBarry Smith         This is somewhat different from MatHeaderReplace() it would be nice to merge the code
352273d9f13SBarry Smith */
353d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHeaderMerge(Mat A, Mat *C)
354d71ae5a4SJacob Faibussowitsch {
355d44834fbSBarry Smith   PetscInt         refct;
35673107ff1SLisandro Dalcin   PetscOps         Abops;
35773107ff1SLisandro Dalcin   struct _MatOps   Aops;
3584768301cSVaclav Hapla   char            *mtype, *mname, *mprefix;
3594222ddf1SHong Zhang   Mat_Product     *product;
36033e6eea4SJose E. Roman   Mat_Redundant   *redundant;
361d4a972cbSStefano Zampini   PetscObjectState state;
362273d9f13SBarry Smith 
363273d9f13SBarry Smith   PetscFunctionBegin;
3641dc04de0SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3651dc04de0SStefano Zampini   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
3663ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
3671dc04de0SStefano Zampini   PetscCheckSameComm(A, 1, *C, 2);
368273d9f13SBarry Smith   /* save the parts of A we need */
36973107ff1SLisandro Dalcin   Abops     = ((PetscObject)A)->bops[0];
37073107ff1SLisandro Dalcin   Aops      = A->ops[0];
3717adad957SLisandro Dalcin   refct     = ((PetscObject)A)->refct;
3725c9eb25fSBarry Smith   mtype     = ((PetscObject)A)->type_name;
3735c9eb25fSBarry Smith   mname     = ((PetscObject)A)->name;
374d4a972cbSStefano Zampini   state     = ((PetscObject)A)->state;
3754768301cSVaclav Hapla   mprefix   = ((PetscObject)A)->prefix;
3764222ddf1SHong Zhang   product   = A->product;
37733e6eea4SJose E. Roman   redundant = A->redundant;
37830735b05SKris Buschelman 
3795c9eb25fSBarry Smith   /* zero these so the destroy below does not free them */
380f4259b30SLisandro Dalcin   ((PetscObject)A)->type_name = NULL;
381f4259b30SLisandro Dalcin   ((PetscObject)A)->name      = NULL;
3825c9eb25fSBarry Smith 
383dbbe0bcdSBarry Smith   /*
384dbbe0bcdSBarry Smith      free all the interior data structures from mat
385dbbe0bcdSBarry Smith      cannot use PetscUseTypeMethod(A,destroy); because compiler
386dbbe0bcdSBarry Smith      thinks it may print NULL type_name and name
387dbbe0bcdSBarry Smith   */
388dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, destroy);
3897c99f97cSSatish Balay 
3909566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->defaultvectype));
3913faff063SStefano Zampini   PetscCall(PetscFree(A->defaultrandtype));
3929566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->rmap));
3939566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->cmap));
3949566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDestroy(&((PetscObject)A)->qlist));
3959566063dSJacob Faibussowitsch   PetscCall(PetscObjectListDestroy(&((PetscObject)A)->olist));
3969566063dSJacob Faibussowitsch   PetscCall(PetscComposedQuantitiesDestroy((PetscObject)A));
397273d9f13SBarry Smith 
398273d9f13SBarry Smith   /* copy C over to A */
39926cc229bSBarry Smith   PetscCall(PetscFree(A->factorprefix));
4009566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
401273d9f13SBarry Smith 
402273d9f13SBarry Smith   /* return the parts of A we saved */
40373107ff1SLisandro Dalcin   ((PetscObject)A)->bops[0]   = Abops;
40473107ff1SLisandro Dalcin   A->ops[0]                   = Aops;
4057adad957SLisandro Dalcin   ((PetscObject)A)->refct     = refct;
4067adad957SLisandro Dalcin   ((PetscObject)A)->type_name = mtype;
4077adad957SLisandro Dalcin   ((PetscObject)A)->name      = mname;
4084768301cSVaclav Hapla   ((PetscObject)A)->prefix    = mprefix;
409d4a972cbSStefano Zampini   ((PetscObject)A)->state     = state + 1;
4104222ddf1SHong Zhang   A->product                  = product;
41133e6eea4SJose E. Roman   A->redundant                = redundant;
412273d9f13SBarry Smith 
4135c9eb25fSBarry Smith   /* since these two are copied into A we do not want them destroyed in C */
414f4259b30SLisandro Dalcin   ((PetscObject)*C)->qlist = NULL;
415f4259b30SLisandro Dalcin   ((PetscObject)*C)->olist = NULL;
41626fbe8dcSKarl Rupp 
4179566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(C));
4183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
419273d9f13SBarry Smith }
4208ab5b326SKris Buschelman /*
421eb6b5d47SBarry Smith         Replace A's header with that of C; the C object is then destroyed
422d0f46423SBarry Smith 
423eb6b5d47SBarry Smith         This is essentially code moved from MatDestroy()
424eb6b5d47SBarry Smith 
425eb6b5d47SBarry Smith         This is somewhat different from MatHeaderMerge() it would be nice to merge the code
426b30237c6SBarry Smith 
427b30237c6SBarry Smith         Used in DM hence is declared PETSC_EXTERN
4288ab5b326SKris Buschelman */
429d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatHeaderReplace(Mat A, Mat *C)
430d71ae5a4SJacob Faibussowitsch {
43127b31e29SJed Brown   PetscInt         refct;
432fefd9316SJose E. Roman   PetscObjectState state;
43328be2f97SBarry Smith   struct _p_Mat    buffer;
43481fa06acSBarry Smith   MatStencilInfo   stencil;
4358ab5b326SKris Buschelman 
4368ab5b326SKris Buschelman   PetscFunctionBegin;
43727b31e29SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
43828be2f97SBarry Smith   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
4393ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
44028be2f97SBarry Smith   PetscCheckSameComm(A, 1, *C, 2);
441aed4548fSBarry 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);
4426d7c1e57SBarry Smith 
44328be2f97SBarry Smith   /* swap C and A */
44427b31e29SJed Brown   refct   = ((PetscObject)A)->refct;
445fefd9316SJose E. Roman   state   = ((PetscObject)A)->state;
44681fa06acSBarry Smith   stencil = A->stencil;
4479566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(&buffer, A, sizeof(struct _p_Mat)));
4489566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
4499566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(*C, &buffer, sizeof(struct _p_Mat)));
45027b31e29SJed Brown   ((PetscObject)A)->refct = refct;
451fefd9316SJose E. Roman   ((PetscObject)A)->state = state + 1;
45281fa06acSBarry Smith   A->stencil              = stencil;
45326fbe8dcSKarl Rupp 
454c32d4117SBarry Smith   ((PetscObject)*C)->refct = 1;
4559566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(*C, MATOP_DESTROY, (void (*)(void))NULL));
4569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(C));
4573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4588ab5b326SKris Buschelman }
459e7e92044SBarry Smith 
460e7e92044SBarry Smith /*@
461b470e4b4SRichard Tran Mills   MatBindToCPU - marks a matrix to temporarily stay on the CPU and perform computations on the CPU
462e7e92044SBarry Smith 
4632ef1f0ffSBarry Smith   Logically Collective
4642216c58aSStefano Zampini 
465e7e92044SBarry Smith   Input Parameters:
466e7e92044SBarry Smith + A   - the matrix
46711a5261eSBarry Smith - flg - bind to the CPU if value of `PETSC_TRUE`
468e7e92044SBarry Smith 
46990ea27d8SSatish Balay   Level: intermediate
4702216c58aSStefano Zampini 
4711cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatBoundToCPU()`
472e7e92044SBarry Smith @*/
473d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBindToCPU(Mat A, PetscBool flg)
474d71ae5a4SJacob Faibussowitsch {
4757d871021SStefano Zampini   PetscFunctionBegin;
4762ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4772ffa8ee7SStefano Zampini   PetscValidLogicalCollectiveBool(A, flg, 2);
4782216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
4793ba16761SJacob Faibussowitsch   if (A->boundtocpu == flg) PetscFunctionReturn(PETSC_SUCCESS);
480b470e4b4SRichard Tran Mills   A->boundtocpu = flg;
481dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, bindtocpu, flg);
4822216c58aSStefano Zampini #endif
4833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4842216c58aSStefano Zampini }
4852216c58aSStefano Zampini 
4862216c58aSStefano Zampini /*@
4872216c58aSStefano Zampini   MatBoundToCPU - query if a matrix is bound to the CPU
4882216c58aSStefano Zampini 
4892216c58aSStefano Zampini   Input Parameter:
4902216c58aSStefano Zampini . A - the matrix
4912216c58aSStefano Zampini 
4922216c58aSStefano Zampini   Output Parameter:
4932216c58aSStefano Zampini . flg - the logical flag
4942216c58aSStefano Zampini 
4952216c58aSStefano Zampini   Level: intermediate
4962216c58aSStefano Zampini 
4971cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatBindToCPU()`
4982216c58aSStefano Zampini @*/
499d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBoundToCPU(Mat A, PetscBool *flg)
500d71ae5a4SJacob Faibussowitsch {
5012ffa8ee7SStefano Zampini   PetscFunctionBegin;
5022ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
503dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(flg, 2);
5042216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
5052216c58aSStefano Zampini   *flg = A->boundtocpu;
5062216c58aSStefano Zampini #else
5072216c58aSStefano Zampini   *flg = PETSC_TRUE;
5087d871021SStefano Zampini #endif
5093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
510e7e92044SBarry Smith }
5117e8381f9SStefano Zampini 
512d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO_Basic(Mat A, const PetscScalar coo_v[], InsertMode imode)
513d71ae5a4SJacob Faibussowitsch {
5147e8381f9SStefano Zampini   IS              is_coo_i, is_coo_j;
5157e8381f9SStefano Zampini   const PetscInt *coo_i, *coo_j;
5167e8381f9SStefano Zampini   PetscInt        n, n_i, n_j;
5177e8381f9SStefano Zampini   PetscScalar     zero = 0.;
5187e8381f9SStefano Zampini 
5197e8381f9SStefano Zampini   PetscFunctionBegin;
5209566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_i", (PetscObject *)&is_coo_i));
5219566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_j", (PetscObject *)&is_coo_j));
52228b400f6SJacob Faibussowitsch   PetscCheck(is_coo_i, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_i IS");
52328b400f6SJacob Faibussowitsch   PetscCheck(is_coo_j, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_j IS");
5249566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_i, &n_i));
5259566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_j, &n_j));
52608401ef6SPierre Jolivet   PetscCheck(n_i == n_j, PETSC_COMM_SELF, PETSC_ERR_COR, "Wrong local size %" PetscInt_FMT " != %" PetscInt_FMT, n_i, n_j);
5279566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_i, &coo_i));
5289566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_j, &coo_j));
52948a46eb9SPierre Jolivet   if (imode != ADD_VALUES) PetscCall(MatZeroEntries(A));
53048a46eb9SPierre 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));
5319566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_i, &coo_i));
5329566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_j, &coo_j));
5333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5347e8381f9SStefano Zampini }
5357e8381f9SStefano Zampini 
536d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO_Basic(Mat A, PetscCount ncoo, const PetscInt coo_i[], const PetscInt coo_j[])
537d71ae5a4SJacob Faibussowitsch {
5387e8381f9SStefano Zampini   Mat         preallocator;
5397e8381f9SStefano Zampini   IS          is_coo_i, is_coo_j;
5407e8381f9SStefano Zampini   PetscScalar zero = 0.0;
5417e8381f9SStefano Zampini 
5427e8381f9SStefano Zampini   PetscFunctionBegin;
5439566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
5449566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
5459566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &preallocator));
5469566063dSJacob Faibussowitsch   PetscCall(MatSetType(preallocator, MATPREALLOCATOR));
5479566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(preallocator, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
5489566063dSJacob Faibussowitsch   PetscCall(MatSetLayouts(preallocator, A->rmap, A->cmap));
5499566063dSJacob Faibussowitsch   PetscCall(MatSetUp(preallocator));
55048a46eb9SPierre Jolivet   for (PetscCount n = 0; n < ncoo; n++) PetscCall(MatSetValue(preallocator, coo_i[n], coo_j[n], zero, INSERT_VALUES));
5519566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY));
5529566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY));
5539566063dSJacob Faibussowitsch   PetscCall(MatPreallocatorPreallocate(preallocator, PETSC_TRUE, A));
5549566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&preallocator));
5552c71b3e2SJacob 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);
5569566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncoo, coo_i, PETSC_COPY_VALUES, &is_coo_i));
5579566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncoo, coo_j, PETSC_COPY_VALUES, &is_coo_j));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_i", (PetscObject)is_coo_i));
5599566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_j", (PetscObject)is_coo_j));
5609566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_i));
5619566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_j));
5623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5637e8381f9SStefano Zampini }
5647e8381f9SStefano Zampini 
56556856777SBarry Smith /*@C
566c3dd2894SJed Brown   MatSetPreallocationCOO - set preallocation for matrices using a coordinate format of the entries with global indices
5677e8381f9SStefano Zampini 
568c3339decSBarry Smith   Collective
5697e8381f9SStefano Zampini 
5704165533cSJose E. Roman   Input Parameters:
5717e8381f9SStefano Zampini + A     - matrix being preallocated
57242550becSJunchao Zhang . ncoo  - number of entries
5737e8381f9SStefano Zampini . coo_i - row indices
5747e8381f9SStefano Zampini - coo_j - column indices
5757e8381f9SStefano Zampini 
5767e8381f9SStefano Zampini   Level: beginner
5777e8381f9SStefano Zampini 
578394ed5ebSJunchao Zhang   Notes:
5792ef1f0ffSBarry Smith   The indices `coo_i` and `coo_j` may be modified within this function. The caller should not rely on them
580e8729f6fSJunchao Zhang   having any specific value after this function returns. The arrays can be freed or reused immediately
581e8729f6fSJunchao Zhang   after this function returns.
582e8729f6fSJunchao Zhang 
58311a5261eSBarry Smith   Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
58411a5261eSBarry Smith   but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
585d7547e51SJunchao Zhang   are allowed and will be properly added or inserted to the matrix, unless the matrix option `MAT_IGNORE_OFF_PROC_ENTRIES`
58611a5261eSBarry 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.
5877e8381f9SStefano Zampini 
588d7547e51SJunchao 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
589d7547e51SJunchao Zhang   `MatCreateSeqAIJFromTriple()`. But that is not recommended for iterative applications.
590d7547e51SJunchao Zhang 
5911cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
5922ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOOLocal()`,
5932ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`, `MatCreateSeqAIJFromTriple()`
5947e8381f9SStefano Zampini @*/
595d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
596d71ae5a4SJacob Faibussowitsch {
59782a78a4eSJed Brown   PetscErrorCode (*f)(Mat, PetscCount, const PetscInt[], const PetscInt[]) = NULL;
5987e8381f9SStefano Zampini 
5997e8381f9SStefano Zampini   PetscFunctionBegin;
6007e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
6017e8381f9SStefano Zampini   PetscValidType(A, 1);
6027e8381f9SStefano Zampini   if (ncoo) PetscValidIntPointer(coo_i, 3);
6037e8381f9SStefano Zampini   if (ncoo) PetscValidIntPointer(coo_j, 4);
6049566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
6059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
6069566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOO_C", &f));
607cbc6b225SStefano Zampini 
6089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_PreallCOO, A, 0, 0, 0));
6097e8381f9SStefano Zampini   if (f) {
6109566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
6117e8381f9SStefano Zampini   } else { /* allow fallback, very slow */
6129566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO_Basic(A, ncoo, coo_i, coo_j));
6137e8381f9SStefano Zampini   }
6149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(MAT_PreallCOO, A, 0, 0, 0));
6156834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
616cbc6b225SStefano Zampini   A->nonzerostate++;
6173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6187e8381f9SStefano Zampini }
6197e8381f9SStefano Zampini 
62056856777SBarry Smith /*@C
621c3dd2894SJed Brown   MatSetPreallocationCOOLocal - set preallocation for matrices using a coordinate format of the entries with local indices
622c3dd2894SJed Brown 
623c3339decSBarry Smith   Collective
624c3dd2894SJed Brown 
625c3dd2894SJed Brown   Input Parameters:
626c3dd2894SJed Brown + A     - matrix being preallocated
627c3dd2894SJed Brown . ncoo  - number of entries
628c3dd2894SJed Brown . coo_i - row indices (local numbering; may be modified)
629c3dd2894SJed Brown - coo_j - column indices (local numbering; may be modified)
630c3dd2894SJed Brown 
631c3dd2894SJed Brown   Level: beginner
632c3dd2894SJed Brown 
633c3dd2894SJed Brown   Notes:
63411a5261eSBarry Smith   The local indices are translated using the local to global mapping, thus `MatSetLocalToGlobalMapping()` must have been
63511a5261eSBarry Smith   called prior to this function. For matrices created with `DMCreateMatrix()` the local to global mapping is often already provided.
636c3dd2894SJed Brown 
6372ef1f0ffSBarry Smith   The indices `coo_i` and `coo_j` may be modified within this function. They might be translated to corresponding global
638735d7f90SBarry Smith   indices, but the caller should not rely on them having any specific value after this function returns. The arrays
639735d7f90SBarry Smith   can be freed or reused immediately after this function returns.
640c3dd2894SJed Brown 
64111a5261eSBarry Smith   Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
64211a5261eSBarry Smith   but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
643394ed5ebSJunchao Zhang   are allowed and will be properly added or inserted to the matrix.
644c3dd2894SJed Brown 
6451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
6462ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOO()`,
6472ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`
648c3dd2894SJed Brown @*/
649d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOOLocal(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
650d71ae5a4SJacob Faibussowitsch {
6516834774dSStefano Zampini   PetscErrorCode (*f)(Mat, PetscCount, PetscInt[], PetscInt[]) = NULL;
652c3dd2894SJed Brown 
653c3dd2894SJed Brown   PetscFunctionBegin;
654c3dd2894SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
655c3dd2894SJed Brown   PetscValidType(A, 1);
656c3dd2894SJed Brown   if (ncoo) PetscValidIntPointer(coo_i, 3);
657c3dd2894SJed Brown   if (ncoo) PetscValidIntPointer(coo_j, 4);
6586834774dSStefano 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);
6599566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
6609566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
661cbc6b225SStefano Zampini 
6629566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", &f));
6636834774dSStefano Zampini   if (f) {
6649566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
665cbc6b225SStefano Zampini     A->nonzerostate++;
6666834774dSStefano Zampini   } else {
667cbc6b225SStefano Zampini     ISLocalToGlobalMapping ltog_row, ltog_col;
6689566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A, &ltog_row, &ltog_col));
6699566063dSJacob Faibussowitsch     if (ltog_row) PetscCall(ISLocalToGlobalMappingApply(ltog_row, ncoo, coo_i, coo_i));
6709566063dSJacob Faibussowitsch     if (ltog_col) PetscCall(ISLocalToGlobalMappingApply(ltog_col, ncoo, coo_j, coo_j));
6719566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO(A, ncoo, coo_i, coo_j));
6726834774dSStefano Zampini   }
6736834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
6743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
675c3dd2894SJed Brown }
676c3dd2894SJed Brown 
677c3dd2894SJed Brown /*@
67811a5261eSBarry Smith   MatSetValuesCOO - set values at once in a matrix preallocated using `MatSetPreallocationCOO()`
6797e8381f9SStefano Zampini 
680c3339decSBarry Smith   Collective
6817e8381f9SStefano Zampini 
6824165533cSJose E. Roman   Input Parameters:
6837e8381f9SStefano Zampini + A     - matrix being preallocated
6842ef1f0ffSBarry Smith . coo_v - the matrix values (can be `NULL`)
6857e8381f9SStefano Zampini - imode - the insert mode
6867e8381f9SStefano Zampini 
6877e8381f9SStefano Zampini   Level: beginner
6887e8381f9SStefano Zampini 
68911a5261eSBarry Smith   Notes:
69011a5261eSBarry Smith   The values must follow the order of the indices prescribed with `MatSetPreallocationCOO()` or `MatSetPreallocationCOOLocal()`.
69111a5261eSBarry Smith 
6922ef1f0ffSBarry Smith   When repeated entries are specified in the COO indices the `coo_v` values are first properly summed, regardless of the value of imode.
69311a5261eSBarry Smith   The imode flag indicates if coo_v must be added to the current values of the matrix (`ADD_VALUES`) or overwritten (`INSERT_VALUES`).
69411a5261eSBarry Smith 
69511a5261eSBarry Smith   `MatAssemblyBegin()` and `MatAssemblyEnd()` do not need to be called after this routine. It automatically handles the assembly process.
6967e8381f9SStefano Zampini 
6971cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetPreallocationCOO()`, `MatSetPreallocationCOOLocal()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
6987e8381f9SStefano Zampini @*/
699d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO(Mat A, const PetscScalar coo_v[], InsertMode imode)
700d71ae5a4SJacob Faibussowitsch {
7017e8381f9SStefano Zampini   PetscErrorCode (*f)(Mat, const PetscScalar[], InsertMode) = NULL;
70235cef55dSJunchao Zhang   PetscBool oldFlg;
7037e8381f9SStefano Zampini 
7047e8381f9SStefano Zampini   PetscFunctionBegin;
7057e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7067e8381f9SStefano Zampini   PetscValidType(A, 1);
7077e8381f9SStefano Zampini   MatCheckPreallocated(A, 1);
708bfcc3627SStefano Zampini   PetscValidLogicalCollectiveEnum(A, imode, 3);
7099566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetValuesCOO_C", &f));
7109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_SetVCOO, A, 0, 0, 0));
7117e8381f9SStefano Zampini   if (f) {
71235cef55dSJunchao Zhang     PetscCall((*f)(A, coo_v, imode)); // all known COO implementations do not use MatStash. They do their own off-proc communication
71335cef55dSJunchao Zhang     PetscCall(MatGetOption(A, MAT_NO_OFF_PROC_ENTRIES, &oldFlg));
71435cef55dSJunchao Zhang     PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); // set A->nooffprocentries to avoid costly MatStash scatter in MatAssembly
71535cef55dSJunchao Zhang   } else {
71635cef55dSJunchao Zhang     PetscCall(MatSetValuesCOO_Basic(A, coo_v, imode)); // fall back to MatSetValues, which might use MatStash
7177e8381f9SStefano Zampini   }
7189566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
7199566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
72035cef55dSJunchao Zhang   if (f) PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, oldFlg));
72135cef55dSJunchao Zhang   PetscCall(PetscLogEventEnd(MAT_SetVCOO, A, 0, 0, 0));
7223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7237e8381f9SStefano Zampini }
72465a9ecf2SRichard Tran Mills 
72565a9ecf2SRichard Tran Mills /*@
72665a9ecf2SRichard 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
72765a9ecf2SRichard Tran Mills 
72865a9ecf2SRichard Tran Mills   Input Parameters:
72965a9ecf2SRichard Tran Mills + A   - the matrix
73065a9ecf2SRichard Tran Mills - flg - flag indicating whether the boundtocpu flag should be propagated
73165a9ecf2SRichard Tran Mills 
73265a9ecf2SRichard Tran Mills   Level: developer
73365a9ecf2SRichard Tran Mills 
73465a9ecf2SRichard Tran Mills   Notes:
7352fe279fdSBarry Smith   If the value of flg is set to true, the following will occur
7362fe279fdSBarry Smith +   `MatCreateSubMatrices()` and `MatCreateRedundantMatrix()` - bind created matrices to CPU if the input matrix is bound to the CPU.
7372fe279fdSBarry Smith -   `MatCreateVecs()` - bind created vectors to CPU if the input matrix is bound to the CPU.
73865a9ecf2SRichard Tran Mills 
73965a9ecf2SRichard Tran Mills   The bindingpropagates flag itself is also propagated by the above routines.
74065a9ecf2SRichard Tran Mills 
741fe59aa6dSJacob Faibussowitsch   Developer Notes:
742aa624791SPierre Jolivet   If the fine-scale `DMDA` has the `-dm_bind_below` option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
74365a9ecf2SRichard Tran Mills   on the restriction/interpolation operator to set the bindingpropagates flag to true.
74465a9ecf2SRichard Tran Mills 
7451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `VecSetBindingPropagates()`, `MatGetBindingPropagates()`
74665a9ecf2SRichard Tran Mills @*/
747d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetBindingPropagates(Mat A, PetscBool flg)
748d71ae5a4SJacob Faibussowitsch {
74965a9ecf2SRichard Tran Mills   PetscFunctionBegin;
75065a9ecf2SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
751d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
75265a9ecf2SRichard Tran Mills   A->bindingpropagates = flg;
75365a9ecf2SRichard Tran Mills #endif
7543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75565a9ecf2SRichard Tran Mills }
756e9c74fd6SRichard Tran Mills 
757e9c74fd6SRichard Tran Mills /*@
758e9c74fd6SRichard 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
759e9c74fd6SRichard Tran Mills 
760e9c74fd6SRichard Tran Mills   Input Parameter:
761e9c74fd6SRichard Tran Mills . A - the matrix
762e9c74fd6SRichard Tran Mills 
763e9c74fd6SRichard Tran Mills   Output Parameter:
764e9c74fd6SRichard Tran Mills . flg - flag indicating whether the boundtocpu flag will be propagated
765e9c74fd6SRichard Tran Mills 
766e9c74fd6SRichard Tran Mills   Level: developer
767e9c74fd6SRichard Tran Mills 
7681cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetBindingPropagates()`
769e9c74fd6SRichard Tran Mills @*/
770d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetBindingPropagates(Mat A, PetscBool *flg)
771d71ae5a4SJacob Faibussowitsch {
772e9c74fd6SRichard Tran Mills   PetscFunctionBegin;
773e9c74fd6SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
774e9c74fd6SRichard Tran Mills   PetscValidBoolPointer(flg, 2);
775d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
776e9c74fd6SRichard Tran Mills   *flg = A->bindingpropagates;
777e9c74fd6SRichard Tran Mills #else
778e9c74fd6SRichard Tran Mills   *flg = PETSC_FALSE;
779e9c74fd6SRichard Tran Mills #endif
7803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
781e9c74fd6SRichard Tran Mills }
782