xref: /petsc/src/mat/utils/gcreate.c (revision 0462cc06d86a4b04d8da7c4dbbe0d29bc6def07a)
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
3411a5261eSBarry Smith    with a call to `MatSetFromOptions()`. The default matrix type is
3511a5261eSBarry Smith    `MATAIJ`, using the routines `MatCreateSeqAIJ()` or `MatCreateAIJ()`
367e5f4302SBarry Smith    if you do not set a type in the options database. If you never
3711a5261eSBarry Smith    call `MatSetType()` or `MatSetFromOptions()` it will generate an
38f8ab6608SSatish Balay    error when you try to use the matrix.
3983e1b59cSLois Curfman McInnes 
40d083f849SBarry Smith    Collective
41cb13003dSBarry Smith 
42f69a0ea3SMatthew Knepley    Input Parameter:
43f69a0ea3SMatthew Knepley .  comm - MPI communicator
447807a1faSBarry Smith 
457807a1faSBarry Smith    Output Parameter:
46dc401e71SLois Curfman McInnes .  A - the matrix
47e0b365e2SLois Curfman McInnes 
48273d9f13SBarry Smith    Options Database Keys:
4911a5261eSBarry Smith +    -mat_type seqaij   - `MATSEQAIJ` type, uses `MatCreateSeqAIJ()`
5011a5261eSBarry Smith .    -mat_type mpiaij   - `MATMPIAIJ` type, uses `MatCreateAIJ()`
5111a5261eSBarry Smith .    -mat_type seqdense - `MATSEQDENSE`, uses `MatCreateSeqDense()`
5211a5261eSBarry Smith .    -mat_type mpidense - `MATMPIDENSE` type, uses `MatCreateDense()`
5311a5261eSBarry Smith .    -mat_type seqbaij  - `MATSEQBAIJ` type, uses `MatCreateSeqBAIJ()`
5411a5261eSBarry Smith -    -mat_type mpibaij  - `MATMPIBAIJ` type, uses `MatCreateBAIJ()`
55e0b365e2SLois Curfman McInnes 
562ef1f0ffSBarry Smith    See the manpages for particular formats (e.g., `MATSEQAIJ`)
5783e1b59cSLois Curfman McInnes    for additional format-specific options.
58e0b365e2SLois Curfman McInnes 
59273d9f13SBarry Smith    Level: beginner
60273d9f13SBarry Smith 
612ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
62db781477SPatrick Sanan           `MatCreateSeqDense()`, `MatCreateDense()`,
63db781477SPatrick Sanan           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
64db781477SPatrick Sanan           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
65db781477SPatrick Sanan           `MatConvert()`
66273d9f13SBarry Smith @*/
67d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate(MPI_Comm comm, Mat *A)
68d71ae5a4SJacob Faibussowitsch {
69273d9f13SBarry Smith   Mat B;
70273d9f13SBarry Smith 
71273d9f13SBarry Smith   PetscFunctionBegin;
72f69a0ea3SMatthew Knepley   PetscValidPointer(A, 2);
7397f1f81fSBarry Smith 
740298fd71SBarry Smith   *A = NULL;
759566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
768ba1e511SMatthew Knepley 
779566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(B, MAT_CLASSID, "Mat", "Matrix", "Mat", comm, MatDestroy, MatView));
789566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->rmap));
799566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->cmap));
809566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(VECSTANDARD, &B->defaultvectype));
813faff063SStefano Zampini   PetscCall(PetscStrallocpy(PETSCRANDER48, &B->defaultrandtype));
8226fbe8dcSKarl Rupp 
83b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_UNKNOWN;
84b94d7dedSBarry Smith   B->hermitian                   = PETSC_BOOL3_UNKNOWN;
85b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_UNKNOWN;
86b94d7dedSBarry Smith   B->spd                         = PETSC_BOOL3_UNKNOWN;
87b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_FALSE;
88b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_FALSE;
89b94d7dedSBarry Smith 
9094342113SStefano Zampini   B->congruentlayouts = PETSC_DECIDE;
91273d9f13SBarry Smith   B->preallocated     = PETSC_FALSE;
926f3d89d0SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
936f3d89d0SStefano Zampini   B->boundtocpu = PETSC_TRUE;
946f3d89d0SStefano Zampini #endif
95273d9f13SBarry Smith   *A = B;
963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97273d9f13SBarry Smith }
98273d9f13SBarry Smith 
99422a814eSBarry Smith /*@
10011a5261eSBarry Smith    MatSetErrorIfFailure - Causes `Mat` to generate an immediate error, for example a zero pivot, is detected.
101422a814eSBarry Smith 
102c3339decSBarry Smith    Logically Collective
103422a814eSBarry Smith 
104422a814eSBarry Smith    Input Parameters:
10511a5261eSBarry Smith +  mat -  matrix obtained from `MatCreate()`
10611a5261eSBarry Smith -  flg - `PETSC_TRUE` indicates you want the error generated
107422a814eSBarry Smith 
108422a814eSBarry Smith    Level: advanced
109422a814eSBarry Smith 
11011a5261eSBarry Smith    Note:
11111a5261eSBarry 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
11211a5261eSBarry Smith    or result in a `KSPConvergedReason` indicating the method did not converge.
11311a5261eSBarry Smith 
1142ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `PCSetErrorIfFailure()`, `KSPConvergedReason`, `SNESConvergedReason`
115422a814eSBarry Smith @*/
116d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetErrorIfFailure(Mat mat, PetscBool flg)
117d71ae5a4SJacob Faibussowitsch {
118422a814eSBarry Smith   PetscFunctionBegin;
119422a814eSBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
120422a814eSBarry Smith   PetscValidLogicalCollectiveBool(mat, flg, 2);
12184d44b13SHong Zhang   mat->erroriffailure = flg;
1223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
123422a814eSBarry Smith }
124422a814eSBarry Smith 
125f69a0ea3SMatthew Knepley /*@
126f69a0ea3SMatthew Knepley   MatSetSizes - Sets the local and global sizes, and checks to determine compatibility
127f69a0ea3SMatthew Knepley 
128c3339decSBarry Smith   Collective
129f69a0ea3SMatthew Knepley 
130f69a0ea3SMatthew Knepley   Input Parameters:
131f69a0ea3SMatthew Knepley +  A - the matrix
13211a5261eSBarry Smith .  m - number of local rows (or `PETSC_DECIDE`)
13311a5261eSBarry Smith .  n - number of local columns (or `PETSC_DECIDE`)
13411a5261eSBarry Smith .  M - number of global rows (or `PETSC_DETERMINE`)
13511a5261eSBarry Smith -  N - number of global columns (or `PETSC_DETERMINE`)
136f69a0ea3SMatthew Knepley 
137f69a0ea3SMatthew Knepley    Notes:
1382ef1f0ffSBarry Smith    `m` (`n`) and `M` (`N`) cannot be both `PETSC_DECIDE`
1392ef1f0ffSBarry Smith    If one processor calls this with `M` (`N`) of `PETSC_DECIDE` then all processors must, otherwise the program will hang.
140f69a0ea3SMatthew Knepley 
14111a5261eSBarry Smith    If `PETSC_DECIDE` is not used for the arguments 'm' and 'n', then the
142f69a0ea3SMatthew Knepley    user must ensure that they are chosen to be compatible with the
143f69a0ea3SMatthew Knepley    vectors. To do this, one first considers the matrix-vector product
1442ef1f0ffSBarry Smith    'y = A x'. The `m` that is used in the above routine must match the
1452ef1f0ffSBarry Smith    local size used in the vector creation routine `VecCreateMPI()` for 'y'.
1462ef1f0ffSBarry Smith    Likewise, the `n` used must match that used as the local size in
14711a5261eSBarry Smith    `VecCreateMPI()` for 'x'.
148f69a0ea3SMatthew Knepley 
149f73d5cc4SBarry Smith    You cannot change the sizes once they have been set.
150f73d5cc4SBarry Smith 
15111a5261eSBarry Smith    The sizes must be set before `MatSetUp()` or MatXXXSetPreallocation() is called.
152f73d5cc4SBarry Smith 
153f69a0ea3SMatthew Knepley   Level: beginner
154f69a0ea3SMatthew Knepley 
1552ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatGetSize()`, `PetscSplitOwnership()`
156f69a0ea3SMatthew Knepley @*/
157d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
158d71ae5a4SJacob Faibussowitsch {
159f69a0ea3SMatthew Knepley   PetscFunctionBegin;
1600700a824SBarry Smith   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
161a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, M, 4);
162a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, N, 5);
163aed4548fSBarry 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);
164aed4548fSBarry 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);
1659371c9d4SSatish 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,
1669371c9d4SSatish Balay              A->rmap->n, A->rmap->N);
1679371c9d4SSatish 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,
1689371c9d4SSatish Balay              A->cmap->n, A->cmap->N);
169d0f46423SBarry Smith   A->rmap->n = m;
170d0f46423SBarry Smith   A->cmap->n = n;
17159cb773eSBarry Smith   A->rmap->N = M > -1 ? M : A->rmap->N;
17259cb773eSBarry Smith   A->cmap->N = N > -1 ? N : A->cmap->N;
1733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
174f69a0ea3SMatthew Knepley }
175f69a0ea3SMatthew Knepley 
17605869f15SSatish Balay /*@
177273d9f13SBarry Smith    MatSetFromOptions - Creates a matrix where the type is determined
178273d9f13SBarry Smith    from the options database. Generates a parallel MPI matrix if the
179273d9f13SBarry Smith    communicator has more than one processor.  The default matrix type is
18011a5261eSBarry Smith    `MATAIJ`, using the routines `MatCreateSeqAIJ()` and `MatCreateAIJ()` if
1817e5f4302SBarry Smith    you do not select a type in the options database.
182273d9f13SBarry Smith 
183c3339decSBarry Smith    Collective
184273d9f13SBarry Smith 
185273d9f13SBarry Smith    Input Parameter:
186273d9f13SBarry Smith .  A - the matrix
187273d9f13SBarry Smith 
188273d9f13SBarry Smith    Options Database Keys:
18911a5261eSBarry Smith +    -mat_type seqaij   - `MATSEQAIJ` type, uses `MatCreateSeqAIJ()`
19011a5261eSBarry Smith .    -mat_type mpiaij   - `MATMPIAIJ` type, uses `MatCreateAIJ()`
19111a5261eSBarry Smith .    -mat_type seqdense - `MATSEQDENSE` type, uses `MatCreateSeqDense()`
19211a5261eSBarry Smith .    -mat_type mpidense - `MATMPIDENSE`, uses `MatCreateDense()`
19311a5261eSBarry Smith .    -mat_type seqbaij  - `MATSEQBAIJ`, uses `MatCreateSeqBAIJ()`
19411a5261eSBarry Smith -    -mat_type mpibaij  - `MATMPIBAIJ`, uses `MatCreateBAIJ()`
195273d9f13SBarry Smith 
1962ef1f0ffSBarry Smith    See the manpages for particular formats (e.g., `MATSEQAIJ`)
197273d9f13SBarry Smith    for additional format-specific options.
198bd9ce289SLois Curfman McInnes 
1991d69843bSLois Curfman McInnes    Level: beginner
2001d69843bSLois Curfman McInnes 
201*0462cc06SPierre Jolivet .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
202db781477SPatrick Sanan           `MatCreateSeqDense()`, `MatCreateDense()`,
203db781477SPatrick Sanan           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
204db781477SPatrick Sanan           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
205db781477SPatrick Sanan           `MatConvert()`
2067807a1faSBarry Smith @*/
207d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetFromOptions(Mat B)
208d71ae5a4SJacob Faibussowitsch {
209f3be49caSLisandro Dalcin   const char *deft = MATAIJ;
210f3be49caSLisandro Dalcin   char        type[256];
21169df5c0cSJed Brown   PetscBool   flg, set;
21216e04d98SRichard Tran Mills   PetscInt    bind_below = 0;
213dbb450caSBarry Smith 
2143a40ed3dSBarry Smith   PetscFunctionBegin;
2150700a824SBarry Smith   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
216f3be49caSLisandro Dalcin 
217d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)B);
218535b19f3SBarry Smith 
219535b19f3SBarry Smith   if (B->rmap->bs < 0) {
220535b19f3SBarry Smith     PetscInt newbs = -1;
2219566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-mat_block_size", "Set the blocksize used to store the matrix", "MatSetBlockSize", newbs, &newbs, &flg));
222535b19f3SBarry Smith     if (flg) {
2239566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->rmap, newbs));
2249566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->cmap, newbs));
225535b19f3SBarry Smith     }
226535b19f3SBarry Smith   }
227535b19f3SBarry Smith 
2289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-mat_type", "Matrix type", "MatSetType", MatList, deft, type, 256, &flg));
229273d9f13SBarry Smith   if (flg) {
2309566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, type));
231f3be49caSLisandro Dalcin   } else if (!((PetscObject)B)->type_name) {
2329566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, deft));
233273d9f13SBarry Smith   }
234f3be49caSLisandro Dalcin 
2359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", &B->checksymmetryonassembly));
2369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", B->checksymmetrytol, &B->checksymmetrytol, NULL));
2379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_null_space_test", "Checks if provided null space is correct in MatAssemblyEnd()", "MatSetNullSpaceTest", B->checknullspaceonassembly, &B->checknullspaceonassembly, NULL));
2389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_error_if_failure", "Generate an error if an error occurs when factoring the matrix", "MatSetErrorIfFailure", B->erroriffailure, &B->erroriffailure, NULL));
239840d65ccSBarry Smith 
240dbbe0bcdSBarry Smith   PetscTryTypeMethod(B, setfromoptions, PetscOptionsObject);
241f3be49caSLisandro Dalcin 
24269df5c0cSJed Brown   flg = PETSC_FALSE;
2439566063dSJacob 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));
2449566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, flg));
24569df5c0cSJed Brown   flg = PETSC_FALSE;
2469566063dSJacob 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));
2479566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, flg));
248478db826SMatthew G. Knepley   flg = PETSC_FALSE;
2499566063dSJacob 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));
2509566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_IGNORE_ZERO_ENTRIES, flg));
25169df5c0cSJed Brown 
2521a2c6b5cSJunchao Zhang   flg = PETSC_FALSE;
2539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_form_explicit_transpose", "Hint to form an explicit transpose for operations like MatMultTranspose", "MatSetOption", flg, &flg, &set));
2549566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_FORM_EXPLICIT_TRANSPOSE, flg));
2551a2c6b5cSJunchao Zhang 
25616e04d98SRichard Tran Mills   /* Bind to CPU if below a user-specified size threshold.
25716e04d98SRichard Tran Mills    * This perhaps belongs in the options for the GPU Mat types, but MatBindToCPU() does nothing when called on non-GPU types,
25816e04d98SRichard Tran Mills    * and putting it here makes is more maintainable than duplicating this for all. */
2599566063dSJacob 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));
26048a46eb9SPierre Jolivet   if (flg && B->rmap->n < bind_below) PetscCall(MatBindToCPU(B, PETSC_TRUE));
26116e04d98SRichard Tran Mills 
2625d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
263dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)B, PetscOptionsObject));
264d0609cedSBarry Smith   PetscOptionsEnd();
2653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2667807a1faSBarry Smith }
2677807a1faSBarry Smith 
268987010e7SBarry Smith /*@C
26911a5261eSBarry Smith    MatXAIJSetPreallocation - set preallocation for serial and parallel `MATAIJ`, `MATBAIJ`, and `MATSBAIJ` matrices and their unassembled versions.
27063562e91SJed Brown 
271c3339decSBarry Smith    Collective
27263562e91SJed Brown 
2734165533cSJose E. Roman    Input Parameters:
27463562e91SJed Brown +  A - matrix being preallocated
27563562e91SJed Brown .  bs - block size
27641319c1dSStefano Zampini .  dnnz - number of nonzero column blocks per block row of diagonal part of parallel matrix
27741319c1dSStefano Zampini .  onnz - number of nonzero column blocks per block row of off-diagonal part of parallel matrix
27841319c1dSStefano Zampini .  dnnzu - number of nonzero column blocks per block row of upper-triangular part of diagonal part of parallel matrix
27941319c1dSStefano Zampini -  onnzu - number of nonzero column blocks per block row of upper-triangular part of off-diagonal part of parallel matrix
28063562e91SJed Brown 
28163562e91SJed Brown    Level: beginner
28263562e91SJed Brown 
2832ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`,
284db781477SPatrick Sanan           `PetscSplitOwnership()`
28563562e91SJed Brown @*/
286d71ae5a4SJacob Faibussowitsch PetscErrorCode MatXAIJSetPreallocation(Mat A, PetscInt bs, const PetscInt dnnz[], const PetscInt onnz[], const PetscInt dnnzu[], const PetscInt onnzu[])
287d71ae5a4SJacob Faibussowitsch {
28841319c1dSStefano Zampini   PetscInt cbs;
28963562e91SJed Brown   void (*aij)(void);
290e8bd9bafSStefano Zampini   void (*is)(void);
291990279feSStefano Zampini   void (*hyp)(void) = NULL;
29263562e91SJed Brown 
29363562e91SJed Brown   PetscFunctionBegin;
29441319c1dSStefano Zampini   if (bs != PETSC_DECIDE) { /* don't mess with an already set block size */
2959566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(A, bs));
29641319c1dSStefano Zampini   }
2979566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
2989566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
2999566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSizes(A, &bs, &cbs));
30041319c1dSStefano Zampini   /* these routines assumes bs == cbs, this should be checked somehow */
3019566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(A, bs, 0, dnnz));
3029566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(A, bs, 0, dnnz, 0, onnz));
3039566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(A, bs, 0, dnnzu));
3049566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(A, bs, 0, dnnzu, 0, onnzu));
30563562e91SJed Brown   /*
306e8bd9bafSStefano 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
30763562e91SJed Brown     good before going on with it.
30863562e91SJed Brown   */
3099566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIAIJSetPreallocation_C", &aij));
3109566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatISSetPreallocation_C", &is));
311990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3129566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatHYPRESetPreallocation_C", &hyp));
313990279feSStefano Zampini #endif
31448a46eb9SPierre Jolivet   if (!aij && !is && !hyp) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", &aij));
315990279feSStefano Zampini   if (aij || is || hyp) {
31641319c1dSStefano Zampini     if (bs == cbs && bs == 1) {
3179566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz));
3189566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz, 0, onnz));
3199566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz, 0, onnz));
320990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3219566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz, 0, onnz));
322990279feSStefano Zampini #endif
3233e5f4774SJed Brown     } else { /* Convert block-row precallocation to scalar-row */
32463562e91SJed Brown       PetscInt i, m, *sdnnz, *sonnz;
3259566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(A, &m, NULL));
3269566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2((!!dnnz) * m, &sdnnz, (!!onnz) * m, &sonnz));
327dec54756SJed Brown       for (i = 0; i < m; i++) {
32841319c1dSStefano Zampini         if (dnnz) sdnnz[i] = dnnz[i / bs] * cbs;
32941319c1dSStefano Zampini         if (onnz) sonnz[i] = onnz[i / bs] * cbs;
33063562e91SJed Brown       }
3319566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL));
3329566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
3339566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
334990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3359566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
336990279feSStefano Zampini #endif
3379566063dSJacob Faibussowitsch       PetscCall(PetscFree2(sdnnz, sonnz));
33863562e91SJed Brown     }
33963562e91SJed Brown   }
3403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34163562e91SJed Brown }
34263562e91SJed Brown 
343273d9f13SBarry Smith /*
344eb6b5d47SBarry Smith         Merges some information from Cs header to A; the C object is then destroyed
345d0f46423SBarry Smith 
346d0f46423SBarry Smith         This is somewhat different from MatHeaderReplace() it would be nice to merge the code
347273d9f13SBarry Smith */
348d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHeaderMerge(Mat A, Mat *C)
349d71ae5a4SJacob Faibussowitsch {
350d44834fbSBarry Smith   PetscInt         refct;
35173107ff1SLisandro Dalcin   PetscOps         Abops;
35273107ff1SLisandro Dalcin   struct _MatOps   Aops;
3534768301cSVaclav Hapla   char            *mtype, *mname, *mprefix;
3544222ddf1SHong Zhang   Mat_Product     *product;
35533e6eea4SJose E. Roman   Mat_Redundant   *redundant;
356d4a972cbSStefano Zampini   PetscObjectState state;
357273d9f13SBarry Smith 
358273d9f13SBarry Smith   PetscFunctionBegin;
3591dc04de0SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3601dc04de0SStefano Zampini   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
3613ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
3621dc04de0SStefano Zampini   PetscCheckSameComm(A, 1, *C, 2);
363273d9f13SBarry Smith   /* save the parts of A we need */
36473107ff1SLisandro Dalcin   Abops     = ((PetscObject)A)->bops[0];
36573107ff1SLisandro Dalcin   Aops      = A->ops[0];
3667adad957SLisandro Dalcin   refct     = ((PetscObject)A)->refct;
3675c9eb25fSBarry Smith   mtype     = ((PetscObject)A)->type_name;
3685c9eb25fSBarry Smith   mname     = ((PetscObject)A)->name;
369d4a972cbSStefano Zampini   state     = ((PetscObject)A)->state;
3704768301cSVaclav Hapla   mprefix   = ((PetscObject)A)->prefix;
3714222ddf1SHong Zhang   product   = A->product;
37233e6eea4SJose E. Roman   redundant = A->redundant;
37330735b05SKris Buschelman 
3745c9eb25fSBarry Smith   /* zero these so the destroy below does not free them */
375f4259b30SLisandro Dalcin   ((PetscObject)A)->type_name = NULL;
376f4259b30SLisandro Dalcin   ((PetscObject)A)->name      = NULL;
3775c9eb25fSBarry Smith 
378dbbe0bcdSBarry Smith   /*
379dbbe0bcdSBarry Smith      free all the interior data structures from mat
380dbbe0bcdSBarry Smith      cannot use PetscUseTypeMethod(A,destroy); because compiler
381dbbe0bcdSBarry Smith      thinks it may print NULL type_name and name
382dbbe0bcdSBarry Smith   */
383dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, destroy);
3847c99f97cSSatish Balay 
3859566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->defaultvectype));
3863faff063SStefano Zampini   PetscCall(PetscFree(A->defaultrandtype));
3879566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->rmap));
3889566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->cmap));
3899566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDestroy(&((PetscObject)A)->qlist));
3909566063dSJacob Faibussowitsch   PetscCall(PetscObjectListDestroy(&((PetscObject)A)->olist));
3919566063dSJacob Faibussowitsch   PetscCall(PetscComposedQuantitiesDestroy((PetscObject)A));
392273d9f13SBarry Smith 
393273d9f13SBarry Smith   /* copy C over to A */
39426cc229bSBarry Smith   PetscCall(PetscFree(A->factorprefix));
3959566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
396273d9f13SBarry Smith 
397273d9f13SBarry Smith   /* return the parts of A we saved */
39873107ff1SLisandro Dalcin   ((PetscObject)A)->bops[0]   = Abops;
39973107ff1SLisandro Dalcin   A->ops[0]                   = Aops;
4007adad957SLisandro Dalcin   ((PetscObject)A)->refct     = refct;
4017adad957SLisandro Dalcin   ((PetscObject)A)->type_name = mtype;
4027adad957SLisandro Dalcin   ((PetscObject)A)->name      = mname;
4034768301cSVaclav Hapla   ((PetscObject)A)->prefix    = mprefix;
404d4a972cbSStefano Zampini   ((PetscObject)A)->state     = state + 1;
4054222ddf1SHong Zhang   A->product                  = product;
40633e6eea4SJose E. Roman   A->redundant                = redundant;
407273d9f13SBarry Smith 
4085c9eb25fSBarry Smith   /* since these two are copied into A we do not want them destroyed in C */
409f4259b30SLisandro Dalcin   ((PetscObject)*C)->qlist = NULL;
410f4259b30SLisandro Dalcin   ((PetscObject)*C)->olist = NULL;
41126fbe8dcSKarl Rupp 
4129566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(C));
4133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
414273d9f13SBarry Smith }
4158ab5b326SKris Buschelman /*
416eb6b5d47SBarry Smith         Replace A's header with that of C; the C object is then destroyed
417d0f46423SBarry Smith 
418eb6b5d47SBarry Smith         This is essentially code moved from MatDestroy()
419eb6b5d47SBarry Smith 
420eb6b5d47SBarry Smith         This is somewhat different from MatHeaderMerge() it would be nice to merge the code
421b30237c6SBarry Smith 
422b30237c6SBarry Smith         Used in DM hence is declared PETSC_EXTERN
4238ab5b326SKris Buschelman */
424d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatHeaderReplace(Mat A, Mat *C)
425d71ae5a4SJacob Faibussowitsch {
42627b31e29SJed Brown   PetscInt         refct;
427fefd9316SJose E. Roman   PetscObjectState state;
42828be2f97SBarry Smith   struct _p_Mat    buffer;
42981fa06acSBarry Smith   MatStencilInfo   stencil;
4308ab5b326SKris Buschelman 
4318ab5b326SKris Buschelman   PetscFunctionBegin;
43227b31e29SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
43328be2f97SBarry Smith   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
4343ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
43528be2f97SBarry Smith   PetscCheckSameComm(A, 1, *C, 2);
436aed4548fSBarry 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);
4376d7c1e57SBarry Smith 
43828be2f97SBarry Smith   /* swap C and A */
43927b31e29SJed Brown   refct   = ((PetscObject)A)->refct;
440fefd9316SJose E. Roman   state   = ((PetscObject)A)->state;
44181fa06acSBarry Smith   stencil = A->stencil;
4429566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(&buffer, A, sizeof(struct _p_Mat)));
4439566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
4449566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(*C, &buffer, sizeof(struct _p_Mat)));
44527b31e29SJed Brown   ((PetscObject)A)->refct = refct;
446fefd9316SJose E. Roman   ((PetscObject)A)->state = state + 1;
44781fa06acSBarry Smith   A->stencil              = stencil;
44826fbe8dcSKarl Rupp 
449c32d4117SBarry Smith   ((PetscObject)*C)->refct = 1;
4509566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(*C, MATOP_DESTROY, (void (*)(void))NULL));
4519566063dSJacob Faibussowitsch   PetscCall(MatDestroy(C));
4523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4538ab5b326SKris Buschelman }
454e7e92044SBarry Smith 
455e7e92044SBarry Smith /*@
456b470e4b4SRichard Tran Mills      MatBindToCPU - marks a matrix to temporarily stay on the CPU and perform computations on the CPU
457e7e92044SBarry Smith 
4582ef1f0ffSBarry Smith    Logically Collective
4592216c58aSStefano Zampini 
460e7e92044SBarry Smith    Input Parameters:
461e7e92044SBarry Smith +   A - the matrix
46211a5261eSBarry Smith -   flg - bind to the CPU if value of `PETSC_TRUE`
463e7e92044SBarry Smith 
46490ea27d8SSatish Balay    Level: intermediate
4652216c58aSStefano Zampini 
4662ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatBoundToCPU()`
467e7e92044SBarry Smith @*/
468d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBindToCPU(Mat A, PetscBool flg)
469d71ae5a4SJacob Faibussowitsch {
4707d871021SStefano Zampini   PetscFunctionBegin;
4712ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4722ffa8ee7SStefano Zampini   PetscValidLogicalCollectiveBool(A, flg, 2);
4732216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
4743ba16761SJacob Faibussowitsch   if (A->boundtocpu == flg) PetscFunctionReturn(PETSC_SUCCESS);
475b470e4b4SRichard Tran Mills   A->boundtocpu = flg;
476dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, bindtocpu, flg);
4772216c58aSStefano Zampini #endif
4783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4792216c58aSStefano Zampini }
4802216c58aSStefano Zampini 
4812216c58aSStefano Zampini /*@
4822216c58aSStefano Zampini      MatBoundToCPU - query if a matrix is bound to the CPU
4832216c58aSStefano Zampini 
4842216c58aSStefano Zampini    Input Parameter:
4852216c58aSStefano Zampini .   A - the matrix
4862216c58aSStefano Zampini 
4872216c58aSStefano Zampini    Output Parameter:
4882216c58aSStefano Zampini .   flg - the logical flag
4892216c58aSStefano Zampini 
4902216c58aSStefano Zampini    Level: intermediate
4912216c58aSStefano Zampini 
4922ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatBindToCPU()`
4932216c58aSStefano Zampini @*/
494d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBoundToCPU(Mat A, PetscBool *flg)
495d71ae5a4SJacob Faibussowitsch {
4962ffa8ee7SStefano Zampini   PetscFunctionBegin;
4972ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
498dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(flg, 2);
4992216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
5002216c58aSStefano Zampini   *flg = A->boundtocpu;
5012216c58aSStefano Zampini #else
5022216c58aSStefano Zampini   *flg = PETSC_TRUE;
5037d871021SStefano Zampini #endif
5043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
505e7e92044SBarry Smith }
5067e8381f9SStefano Zampini 
507d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO_Basic(Mat A, const PetscScalar coo_v[], InsertMode imode)
508d71ae5a4SJacob Faibussowitsch {
5097e8381f9SStefano Zampini   IS              is_coo_i, is_coo_j;
5107e8381f9SStefano Zampini   const PetscInt *coo_i, *coo_j;
5117e8381f9SStefano Zampini   PetscInt        n, n_i, n_j;
5127e8381f9SStefano Zampini   PetscScalar     zero = 0.;
5137e8381f9SStefano Zampini 
5147e8381f9SStefano Zampini   PetscFunctionBegin;
5159566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_i", (PetscObject *)&is_coo_i));
5169566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_j", (PetscObject *)&is_coo_j));
51728b400f6SJacob Faibussowitsch   PetscCheck(is_coo_i, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_i IS");
51828b400f6SJacob Faibussowitsch   PetscCheck(is_coo_j, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_j IS");
5199566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_i, &n_i));
5209566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_j, &n_j));
52108401ef6SPierre Jolivet   PetscCheck(n_i == n_j, PETSC_COMM_SELF, PETSC_ERR_COR, "Wrong local size %" PetscInt_FMT " != %" PetscInt_FMT, n_i, n_j);
5229566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_i, &coo_i));
5239566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_j, &coo_j));
52448a46eb9SPierre Jolivet   if (imode != ADD_VALUES) PetscCall(MatZeroEntries(A));
52548a46eb9SPierre 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));
5269566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_i, &coo_i));
5279566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_j, &coo_j));
5283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5297e8381f9SStefano Zampini }
5307e8381f9SStefano Zampini 
531d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO_Basic(Mat A, PetscCount ncoo, const PetscInt coo_i[], const PetscInt coo_j[])
532d71ae5a4SJacob Faibussowitsch {
5337e8381f9SStefano Zampini   Mat         preallocator;
5347e8381f9SStefano Zampini   IS          is_coo_i, is_coo_j;
5357e8381f9SStefano Zampini   PetscScalar zero = 0.0;
5367e8381f9SStefano Zampini 
5377e8381f9SStefano Zampini   PetscFunctionBegin;
5389566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
5399566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
5409566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &preallocator));
5419566063dSJacob Faibussowitsch   PetscCall(MatSetType(preallocator, MATPREALLOCATOR));
5429566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(preallocator, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
5439566063dSJacob Faibussowitsch   PetscCall(MatSetLayouts(preallocator, A->rmap, A->cmap));
5449566063dSJacob Faibussowitsch   PetscCall(MatSetUp(preallocator));
54548a46eb9SPierre Jolivet   for (PetscCount n = 0; n < ncoo; n++) PetscCall(MatSetValue(preallocator, coo_i[n], coo_j[n], zero, INSERT_VALUES));
5469566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY));
5479566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY));
5489566063dSJacob Faibussowitsch   PetscCall(MatPreallocatorPreallocate(preallocator, PETSC_TRUE, A));
5499566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&preallocator));
5502c71b3e2SJacob 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);
5519566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncoo, coo_i, PETSC_COPY_VALUES, &is_coo_i));
5529566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncoo, coo_j, PETSC_COPY_VALUES, &is_coo_j));
5539566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_i", (PetscObject)is_coo_i));
5549566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_j", (PetscObject)is_coo_j));
5559566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_i));
5569566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_j));
5573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5587e8381f9SStefano Zampini }
5597e8381f9SStefano Zampini 
56056856777SBarry Smith /*@C
561c3dd2894SJed Brown    MatSetPreallocationCOO - set preallocation for matrices using a coordinate format of the entries with global indices
5627e8381f9SStefano Zampini 
563c3339decSBarry Smith    Collective
5647e8381f9SStefano Zampini 
5654165533cSJose E. Roman    Input Parameters:
5667e8381f9SStefano Zampini +  A - matrix being preallocated
56742550becSJunchao Zhang .  ncoo - number of entries
5687e8381f9SStefano Zampini .  coo_i - row indices
5697e8381f9SStefano Zampini -  coo_j - column indices
5707e8381f9SStefano Zampini 
5717e8381f9SStefano Zampini    Level: beginner
5727e8381f9SStefano Zampini 
573394ed5ebSJunchao Zhang    Notes:
5742ef1f0ffSBarry Smith    The indices `coo_i` and `coo_j` may be modified within this function. The caller should not rely on them
575e8729f6fSJunchao Zhang    having any specific value after this function returns. The arrays can be freed or reused immediately
576e8729f6fSJunchao Zhang    after this function returns.
577e8729f6fSJunchao Zhang 
57811a5261eSBarry Smith    Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
57911a5261eSBarry Smith    but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
580d7547e51SJunchao Zhang    are allowed and will be properly added or inserted to the matrix, unless the matrix option `MAT_IGNORE_OFF_PROC_ENTRIES`
58111a5261eSBarry 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.
5827e8381f9SStefano Zampini 
583d7547e51SJunchao 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
584d7547e51SJunchao Zhang    `MatCreateSeqAIJFromTriple()`. But that is not recommended for iterative applications.
585d7547e51SJunchao Zhang 
5862ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
5872ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOOLocal()`,
5882ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`, `MatCreateSeqAIJFromTriple()`
5897e8381f9SStefano Zampini @*/
590d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
591d71ae5a4SJacob Faibussowitsch {
59282a78a4eSJed Brown   PetscErrorCode (*f)(Mat, PetscCount, const PetscInt[], const PetscInt[]) = NULL;
5937e8381f9SStefano Zampini 
5947e8381f9SStefano Zampini   PetscFunctionBegin;
5957e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5967e8381f9SStefano Zampini   PetscValidType(A, 1);
5977e8381f9SStefano Zampini   if (ncoo) PetscValidIntPointer(coo_i, 3);
5987e8381f9SStefano Zampini   if (ncoo) PetscValidIntPointer(coo_j, 4);
5999566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
6009566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
6019566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOO_C", &f));
602cbc6b225SStefano Zampini 
6039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_PreallCOO, A, 0, 0, 0));
6047e8381f9SStefano Zampini   if (f) {
6059566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
6067e8381f9SStefano Zampini   } else { /* allow fallback, very slow */
6079566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO_Basic(A, ncoo, coo_i, coo_j));
6087e8381f9SStefano Zampini   }
6099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(MAT_PreallCOO, A, 0, 0, 0));
6106834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
611cbc6b225SStefano Zampini   A->nonzerostate++;
6123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6137e8381f9SStefano Zampini }
6147e8381f9SStefano Zampini 
61556856777SBarry Smith /*@C
616c3dd2894SJed Brown    MatSetPreallocationCOOLocal - set preallocation for matrices using a coordinate format of the entries with local indices
617c3dd2894SJed Brown 
618c3339decSBarry Smith    Collective
619c3dd2894SJed Brown 
620c3dd2894SJed Brown    Input Parameters:
621c3dd2894SJed Brown +  A - matrix being preallocated
622c3dd2894SJed Brown .  ncoo - number of entries
623c3dd2894SJed Brown .  coo_i - row indices (local numbering; may be modified)
624c3dd2894SJed Brown -  coo_j - column indices (local numbering; may be modified)
625c3dd2894SJed Brown 
626c3dd2894SJed Brown    Level: beginner
627c3dd2894SJed Brown 
628c3dd2894SJed Brown    Notes:
62911a5261eSBarry Smith    The local indices are translated using the local to global mapping, thus `MatSetLocalToGlobalMapping()` must have been
63011a5261eSBarry Smith    called prior to this function. For matrices created with `DMCreateMatrix()` the local to global mapping is often already provided.
631c3dd2894SJed Brown 
6322ef1f0ffSBarry Smith    The indices `coo_i` and `coo_j` may be modified within this function. They might be translated to corresponding global
633735d7f90SBarry Smith    indices, but the caller should not rely on them having any specific value after this function returns. The arrays
634735d7f90SBarry Smith    can be freed or reused immediately after this function returns.
635c3dd2894SJed Brown 
63611a5261eSBarry Smith    Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
63711a5261eSBarry Smith    but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
638394ed5ebSJunchao Zhang    are allowed and will be properly added or inserted to the matrix.
639c3dd2894SJed Brown 
6402ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
6412ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOO()`,
6422ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`
643c3dd2894SJed Brown @*/
644d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOOLocal(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
645d71ae5a4SJacob Faibussowitsch {
6466834774dSStefano Zampini   PetscErrorCode (*f)(Mat, PetscCount, PetscInt[], PetscInt[]) = NULL;
647c3dd2894SJed Brown 
648c3dd2894SJed Brown   PetscFunctionBegin;
649c3dd2894SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
650c3dd2894SJed Brown   PetscValidType(A, 1);
651c3dd2894SJed Brown   if (ncoo) PetscValidIntPointer(coo_i, 3);
652c3dd2894SJed Brown   if (ncoo) PetscValidIntPointer(coo_j, 4);
6536834774dSStefano 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);
6549566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
6559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
656cbc6b225SStefano Zampini 
6579566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", &f));
6586834774dSStefano Zampini   if (f) {
6599566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
660cbc6b225SStefano Zampini     A->nonzerostate++;
6616834774dSStefano Zampini   } else {
662cbc6b225SStefano Zampini     ISLocalToGlobalMapping ltog_row, ltog_col;
6639566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A, &ltog_row, &ltog_col));
6649566063dSJacob Faibussowitsch     if (ltog_row) PetscCall(ISLocalToGlobalMappingApply(ltog_row, ncoo, coo_i, coo_i));
6659566063dSJacob Faibussowitsch     if (ltog_col) PetscCall(ISLocalToGlobalMappingApply(ltog_col, ncoo, coo_j, coo_j));
6669566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO(A, ncoo, coo_i, coo_j));
6676834774dSStefano Zampini   }
6686834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
6693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
670c3dd2894SJed Brown }
671c3dd2894SJed Brown 
672c3dd2894SJed Brown /*@
67311a5261eSBarry Smith    MatSetValuesCOO - set values at once in a matrix preallocated using `MatSetPreallocationCOO()`
6747e8381f9SStefano Zampini 
675c3339decSBarry Smith    Collective
6767e8381f9SStefano Zampini 
6774165533cSJose E. Roman    Input Parameters:
6787e8381f9SStefano Zampini +  A - matrix being preallocated
6792ef1f0ffSBarry Smith .  coo_v - the matrix values (can be `NULL`)
6807e8381f9SStefano Zampini -  imode - the insert mode
6817e8381f9SStefano Zampini 
6827e8381f9SStefano Zampini    Level: beginner
6837e8381f9SStefano Zampini 
68411a5261eSBarry Smith    Notes:
68511a5261eSBarry Smith    The values must follow the order of the indices prescribed with `MatSetPreallocationCOO()` or `MatSetPreallocationCOOLocal()`.
68611a5261eSBarry Smith 
6872ef1f0ffSBarry Smith           When repeated entries are specified in the COO indices the `coo_v` values are first properly summed, regardless of the value of imode.
68811a5261eSBarry Smith           The imode flag indicates if coo_v must be added to the current values of the matrix (`ADD_VALUES`) or overwritten (`INSERT_VALUES`).
68911a5261eSBarry Smith 
69011a5261eSBarry Smith           `MatAssemblyBegin()` and `MatAssemblyEnd()` do not need to be called after this routine. It automatically handles the assembly process.
6917e8381f9SStefano Zampini 
6922ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSetPreallocationCOO()`, `MatSetPreallocationCOOLocal()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
6937e8381f9SStefano Zampini @*/
694d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO(Mat A, const PetscScalar coo_v[], InsertMode imode)
695d71ae5a4SJacob Faibussowitsch {
6967e8381f9SStefano Zampini   PetscErrorCode (*f)(Mat, const PetscScalar[], InsertMode) = NULL;
6977e8381f9SStefano Zampini 
6987e8381f9SStefano Zampini   PetscFunctionBegin;
6997e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7007e8381f9SStefano Zampini   PetscValidType(A, 1);
7017e8381f9SStefano Zampini   MatCheckPreallocated(A, 1);
702bfcc3627SStefano Zampini   PetscValidLogicalCollectiveEnum(A, imode, 3);
7039566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetValuesCOO_C", &f));
7049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_SetVCOO, A, 0, 0, 0));
7057e8381f9SStefano Zampini   if (f) {
7069566063dSJacob Faibussowitsch     PetscCall((*f)(A, coo_v, imode));
7077e8381f9SStefano Zampini   } else { /* allow fallback */
7089566063dSJacob Faibussowitsch     PetscCall(MatSetValuesCOO_Basic(A, coo_v, imode));
7097e8381f9SStefano Zampini   }
7109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(MAT_SetVCOO, A, 0, 0, 0));
7119566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
7129566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
7133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7147e8381f9SStefano Zampini }
71565a9ecf2SRichard Tran Mills 
71665a9ecf2SRichard Tran Mills /*@
71765a9ecf2SRichard 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
71865a9ecf2SRichard Tran Mills 
71965a9ecf2SRichard Tran Mills    Input Parameters:
72065a9ecf2SRichard Tran Mills +  A - the matrix
72165a9ecf2SRichard Tran Mills -  flg - flag indicating whether the boundtocpu flag should be propagated
72265a9ecf2SRichard Tran Mills 
72365a9ecf2SRichard Tran Mills    Level: developer
72465a9ecf2SRichard Tran Mills 
72565a9ecf2SRichard Tran Mills    Notes:
72665a9ecf2SRichard Tran Mills    If the value of flg is set to true, the following will occur:
72765a9ecf2SRichard Tran Mills 
72811a5261eSBarry Smith    `MatCreateSubMatrices()` and `MatCreateRedundantMatrix()` will bind created matrices to CPU if the input matrix is bound to the CPU.
72911a5261eSBarry Smith 
73011a5261eSBarry Smith    `MatCreateVecs()` will bind created vectors to CPU if the input matrix is bound to the CPU.
73165a9ecf2SRichard Tran Mills    The bindingpropagates flag itself is also propagated by the above routines.
73265a9ecf2SRichard Tran Mills 
73311a5261eSBarry Smith    Developer Note:
734aa624791SPierre Jolivet    If the fine-scale `DMDA` has the `-dm_bind_below` option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
73565a9ecf2SRichard Tran Mills    on the restriction/interpolation operator to set the bindingpropagates flag to true.
73665a9ecf2SRichard Tran Mills 
7372ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `VecSetBindingPropagates()`, `MatGetBindingPropagates()`
73865a9ecf2SRichard Tran Mills @*/
739d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetBindingPropagates(Mat A, PetscBool flg)
740d71ae5a4SJacob Faibussowitsch {
74165a9ecf2SRichard Tran Mills   PetscFunctionBegin;
74265a9ecf2SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
743d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
74465a9ecf2SRichard Tran Mills   A->bindingpropagates = flg;
74565a9ecf2SRichard Tran Mills #endif
7463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74765a9ecf2SRichard Tran Mills }
748e9c74fd6SRichard Tran Mills 
749e9c74fd6SRichard Tran Mills /*@
750e9c74fd6SRichard 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
751e9c74fd6SRichard Tran Mills 
752e9c74fd6SRichard Tran Mills    Input Parameter:
753e9c74fd6SRichard Tran Mills .  A - the matrix
754e9c74fd6SRichard Tran Mills 
755e9c74fd6SRichard Tran Mills    Output Parameter:
756e9c74fd6SRichard Tran Mills .  flg - flag indicating whether the boundtocpu flag will be propagated
757e9c74fd6SRichard Tran Mills 
758e9c74fd6SRichard Tran Mills    Level: developer
759e9c74fd6SRichard Tran Mills 
7602ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MatSetBindingPropagates()`
761e9c74fd6SRichard Tran Mills @*/
762d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetBindingPropagates(Mat A, PetscBool *flg)
763d71ae5a4SJacob Faibussowitsch {
764e9c74fd6SRichard Tran Mills   PetscFunctionBegin;
765e9c74fd6SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
766e9c74fd6SRichard Tran Mills   PetscValidBoolPointer(flg, 2);
767d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
768e9c74fd6SRichard Tran Mills   *flg = A->bindingpropagates;
769e9c74fd6SRichard Tran Mills #else
770e9c74fd6SRichard Tran Mills   *flg = PETSC_FALSE;
771e9c74fd6SRichard Tran Mills #endif
7723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
773e9c74fd6SRichard Tran Mills }
774