xref: /petsc/src/dm/impls/sliced/sliced.c (revision 2fe279fdf3e687a416e4eadb7d3c7a82d60442c6)
1c6db04a5SJed Brown #include <petscdmsliced.h> /*I      "petscdmsliced.h" I*/
207475bc1SBarry Smith #include <petscmat.h>
3af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
447c6ae99SBarry Smith 
547c6ae99SBarry Smith /* CSR storage of the nonzero structure of a bs*bs matrix */
647c6ae99SBarry Smith typedef struct {
747c6ae99SBarry Smith   PetscInt bs, nz, *i, *j;
80c010503SBarry Smith } DMSlicedBlockFills;
947c6ae99SBarry Smith 
1047c6ae99SBarry Smith typedef struct {
1147c6ae99SBarry Smith   PetscInt            bs, n, N, Nghosts, *ghosts;
1247c6ae99SBarry Smith   PetscInt            d_nz, o_nz, *d_nnz, *o_nnz;
130c010503SBarry Smith   DMSlicedBlockFills *dfill, *ofill;
1447c6ae99SBarry Smith } DM_Sliced;
1547c6ae99SBarry Smith 
16d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Sliced(DM dm, Mat *J)
17d71ae5a4SJacob Faibussowitsch {
1847c6ae99SBarry Smith   PetscInt              *globals, *sd_nnz, *so_nnz, rstart, bs, i;
1945b6f7e9SBarry Smith   ISLocalToGlobalMapping lmap;
20f77a5242SKarl Rupp   void (*aij)(void) = NULL;
2147c6ae99SBarry Smith   DM_Sliced *slice  = (DM_Sliced *)dm->data;
2247c6ae99SBarry Smith 
2347c6ae99SBarry Smith   PetscFunctionBegin;
2447c6ae99SBarry Smith   bs = slice->bs;
259566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
269566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, slice->n * bs, slice->n * bs, PETSC_DETERMINE, PETSC_DETERMINE));
279566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(*J, bs));
289566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, dm->mattype));
299566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(*J, bs, slice->d_nz, slice->d_nnz));
309566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(*J, bs, slice->d_nz, slice->d_nnz, slice->o_nz, slice->o_nnz));
3147c6ae99SBarry Smith   /* In general, we have to do extra work to preallocate for scalar (AIJ) matrices so we check whether it will do any
3247c6ae99SBarry Smith   * good before going on with it. */
339566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)*J, "MatMPIAIJSetPreallocation_C", &aij));
3448a46eb9SPierre Jolivet   if (!aij) PetscCall(PetscObjectQueryFunction((PetscObject)*J, "MatSeqAIJSetPreallocation_C", &aij));
3547c6ae99SBarry Smith   if (aij) {
3647c6ae99SBarry Smith     if (bs == 1) {
379566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(*J, slice->d_nz, slice->d_nnz));
389566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(*J, slice->d_nz, slice->d_nnz, slice->o_nz, slice->o_nnz));
3947c6ae99SBarry Smith     } else if (!slice->d_nnz) {
409566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(*J, slice->d_nz * bs, NULL));
419566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(*J, slice->d_nz * bs, NULL, slice->o_nz * bs, NULL));
4247c6ae99SBarry Smith     } else {
430c010503SBarry Smith       /* The user has provided preallocation per block-row, convert it to per scalar-row respecting DMSlicedSetBlockFills() if applicable */
449566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(slice->n * bs, &sd_nnz, (!!slice->o_nnz) * slice->n * bs, &so_nnz));
4547c6ae99SBarry Smith       for (i = 0; i < slice->n * bs; i++) {
469371c9d4SSatish Balay         sd_nnz[i] = (slice->d_nnz[i / bs] - 1) * (slice->ofill ? slice->ofill->i[i % bs + 1] - slice->ofill->i[i % bs] : bs) + (slice->dfill ? slice->dfill->i[i % bs + 1] - slice->dfill->i[i % bs] : bs);
47ad540459SPierre Jolivet         if (so_nnz) so_nnz[i] = slice->o_nnz[i / bs] * (slice->ofill ? slice->ofill->i[i % bs + 1] - slice->ofill->i[i % bs] : bs);
4847c6ae99SBarry Smith       }
499566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(*J, slice->d_nz * bs, sd_nnz));
509566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(*J, slice->d_nz * bs, sd_nnz, slice->o_nz * bs, so_nnz));
519566063dSJacob Faibussowitsch       PetscCall(PetscFree2(sd_nnz, so_nnz));
5247c6ae99SBarry Smith     }
5347c6ae99SBarry Smith   }
5447c6ae99SBarry Smith 
5547c6ae99SBarry Smith   /* Set up the local to global map.  For the scalar map, we have to translate to entry-wise indexing instead of block-wise. */
569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(slice->n + slice->Nghosts, &globals));
579566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(*J, &rstart, NULL));
5845b6f7e9SBarry Smith   for (i = 0; i < slice->n; i++) globals[i] = rstart / bs + i;
598865f1eaSKarl Rupp 
60ad540459SPierre Jolivet   for (i = 0; i < slice->Nghosts; i++) globals[slice->n + i] = slice->ghosts[i];
619566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, bs, slice->n + slice->Nghosts, globals, PETSC_OWN_POINTER, &lmap));
629566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(*J, lmap, lmap));
639566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&lmap));
649566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6647c6ae99SBarry Smith }
6747c6ae99SBarry Smith 
6847c6ae99SBarry Smith /*@C
690c010503SBarry Smith     DMSlicedSetGhosts - Sets the global indices of other processes elements that will
7047c6ae99SBarry Smith       be ghosts on this process
7147c6ae99SBarry Smith 
7247c6ae99SBarry Smith     Not Collective
7347c6ae99SBarry Smith 
7447c6ae99SBarry Smith     Input Parameters:
7520f4b53cSBarry Smith +    slice - the `DMSLICED` object
7647c6ae99SBarry Smith .    bs - block size
7747c6ae99SBarry Smith .    nlocal - number of local (owned, non-ghost) blocks
7847c6ae99SBarry Smith .    Nghosts - number of ghost blocks on this process
7947c6ae99SBarry Smith -    ghosts - global indices of each ghost block
8047c6ae99SBarry Smith 
8147c6ae99SBarry Smith     Level: advanced
8247c6ae99SBarry Smith 
83*2fe279fdSBarry Smith .seealso: `DM`, `DMSLICED`, `DMDestroy()`, `DMCreateGlobalVector()`
8447c6ae99SBarry Smith @*/
85d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSlicedSetGhosts(DM dm, PetscInt bs, PetscInt nlocal, PetscInt Nghosts, const PetscInt ghosts[])
86d71ae5a4SJacob Faibussowitsch {
8747c6ae99SBarry Smith   DM_Sliced *slice = (DM_Sliced *)dm->data;
8847c6ae99SBarry Smith 
8947c6ae99SBarry Smith   PetscFunctionBegin;
900c010503SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
919566063dSJacob Faibussowitsch   PetscCall(PetscFree(slice->ghosts));
929566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(Nghosts, &slice->ghosts));
939566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(slice->ghosts, ghosts, Nghosts));
9447c6ae99SBarry Smith   slice->bs      = bs;
9547c6ae99SBarry Smith   slice->n       = nlocal;
9647c6ae99SBarry Smith   slice->Nghosts = Nghosts;
973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9847c6ae99SBarry Smith }
9947c6ae99SBarry Smith 
10047c6ae99SBarry Smith /*@C
101*2fe279fdSBarry Smith     DMSlicedSetPreallocation - sets the matrix memory preallocation for matrices computed by `DMSLICED`
10247c6ae99SBarry Smith 
10347c6ae99SBarry Smith     Not Collective
10447c6ae99SBarry Smith 
10547c6ae99SBarry Smith     Input Parameters:
10620f4b53cSBarry Smith +    slice - the `DM` object
10747c6ae99SBarry Smith .    d_nz  - number of block nonzeros per block row in diagonal portion of local
10847c6ae99SBarry Smith            submatrix  (same for all local rows)
10947c6ae99SBarry Smith .    d_nnz - array containing the number of block nonzeros in the various block rows
11047c6ae99SBarry Smith            of the in diagonal portion of the local (possibly different for each block
111*2fe279fdSBarry Smith            row) or `NULL`.
11247c6ae99SBarry Smith .    o_nz  - number of block nonzeros per block row in the off-diagonal portion of local
11347c6ae99SBarry Smith            submatrix (same for all local rows).
11447c6ae99SBarry Smith -    o_nnz - array containing the number of nonzeros in the various block rows of the
11547c6ae99SBarry Smith            off-diagonal portion of the local submatrix (possibly different for
11620f4b53cSBarry Smith            each block row) or `NULL`.
11747c6ae99SBarry Smith 
11847c6ae99SBarry Smith     Level: advanced
11947c6ae99SBarry Smith 
12020f4b53cSBarry Smith     Note:
121*2fe279fdSBarry Smith     See `MatMPIBAIJSetPreallocation()` for more details on preallocation.  If a scalar matrix (`MATAIJ`) is
12220f4b53cSBarry Smith     obtained with `DMSlicedGetMatrix()`, the correct preallocation will be set, respecting `DMSlicedSetBlockFills()`.
12320f4b53cSBarry Smith 
124*2fe279fdSBarry Smith .seealso: `DM`, `DMSLICED`, `DMDestroy()`, `DMCreateGlobalVector()`, `MatMPIAIJSetPreallocation()`,
125db781477SPatrick Sanan          `MatMPIBAIJSetPreallocation()`, `DMSlicedGetMatrix()`, `DMSlicedSetBlockFills()`
12647c6ae99SBarry Smith @*/
127d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSlicedSetPreallocation(DM dm, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[])
128d71ae5a4SJacob Faibussowitsch {
12947c6ae99SBarry Smith   DM_Sliced *slice = (DM_Sliced *)dm->data;
13047c6ae99SBarry Smith 
13147c6ae99SBarry Smith   PetscFunctionBegin;
13247c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
13347c6ae99SBarry Smith   slice->d_nz  = d_nz;
13447c6ae99SBarry Smith   slice->d_nnz = (PetscInt *)d_nnz;
13547c6ae99SBarry Smith   slice->o_nz  = o_nz;
13647c6ae99SBarry Smith   slice->o_nnz = (PetscInt *)o_nnz;
1373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13847c6ae99SBarry Smith }
13947c6ae99SBarry Smith 
140d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSlicedSetBlockFills_Private(PetscInt bs, const PetscInt *fill, DMSlicedBlockFills **inf)
141d71ae5a4SJacob Faibussowitsch {
14247c6ae99SBarry Smith   PetscInt            i, j, nz, *fi, *fj;
1430c010503SBarry Smith   DMSlicedBlockFills *f;
14447c6ae99SBarry Smith 
14547c6ae99SBarry Smith   PetscFunctionBegin;
14647c6ae99SBarry Smith   PetscValidPointer(inf, 3);
1479566063dSJacob Faibussowitsch   if (*inf) PetscCall(PetscFree3(*inf, (*inf)->i, (*inf)->j));
1483ba16761SJacob Faibussowitsch   if (!fill) PetscFunctionReturn(PETSC_SUCCESS);
1499371c9d4SSatish Balay   for (i = 0, nz = 0; i < bs * bs; i++)
1509371c9d4SSatish Balay     if (fill[i]) nz++;
1519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(1, &f, bs + 1, &fi, nz, &fj));
15247c6ae99SBarry Smith   f->bs = bs;
15347c6ae99SBarry Smith   f->nz = nz;
15447c6ae99SBarry Smith   f->i  = fi;
15547c6ae99SBarry Smith   f->j  = fj;
15647c6ae99SBarry Smith   for (i = 0, nz = 0; i < bs; i++) {
15747c6ae99SBarry Smith     fi[i] = nz;
1589371c9d4SSatish Balay     for (j = 0; j < bs; j++)
1599371c9d4SSatish Balay       if (fill[i * bs + j]) fj[nz++] = j;
16047c6ae99SBarry Smith   }
16147c6ae99SBarry Smith   fi[i] = nz;
16247c6ae99SBarry Smith   *inf  = f;
1633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16447c6ae99SBarry Smith }
16547c6ae99SBarry Smith 
16647c6ae99SBarry Smith /*@C
1670c010503SBarry Smith     DMSlicedSetBlockFills - Sets the fill pattern in each block for a multi-component problem
16820f4b53cSBarry Smith     of the matrix returned by `DMSlicedGetMatrix()`.
16947c6ae99SBarry Smith 
17020f4b53cSBarry Smith     Logically Collective
17147c6ae99SBarry Smith 
172d8d19677SJose E. Roman     Input Parameters:
17320f4b53cSBarry Smith +   sliced - the `DM` object
17420f4b53cSBarry Smith .   dfill - the fill pattern in the diagonal block (may be `NULL`, means use dense block)
17547c6ae99SBarry Smith -   ofill - the fill pattern in the off-diagonal blocks
17647c6ae99SBarry Smith 
17747c6ae99SBarry Smith     Level: advanced
17847c6ae99SBarry Smith 
17920f4b53cSBarry Smith     Note:
18020f4b53cSBarry Smith     This only makes sense for multicomponent problems using scalar matrix formats (AIJ).
18120f4b53cSBarry Smith     See `DMDASetBlockFills()` for example usage.
18220f4b53cSBarry Smith 
183*2fe279fdSBarry Smith .seealso: `DM`, `DMSLICED`, `DMSlicedGetMatrix()`, `DMDASetBlockFills()`
18447c6ae99SBarry Smith @*/
185d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSlicedSetBlockFills(DM dm, const PetscInt *dfill, const PetscInt *ofill)
186d71ae5a4SJacob Faibussowitsch {
18747c6ae99SBarry Smith   DM_Sliced *slice = (DM_Sliced *)dm->data;
18847c6ae99SBarry Smith 
18947c6ae99SBarry Smith   PetscFunctionBegin;
1900c010503SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1919566063dSJacob Faibussowitsch   PetscCall(DMSlicedSetBlockFills_Private(slice->bs, dfill, &slice->dfill));
1929566063dSJacob Faibussowitsch   PetscCall(DMSlicedSetBlockFills_Private(slice->bs, ofill, &slice->ofill));
1933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19447c6ae99SBarry Smith }
19547c6ae99SBarry Smith 
196d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDestroy_Sliced(DM dm)
197d71ae5a4SJacob Faibussowitsch {
19847c6ae99SBarry Smith   DM_Sliced *slice = (DM_Sliced *)dm->data;
19947c6ae99SBarry Smith 
20047c6ae99SBarry Smith   PetscFunctionBegin;
2019566063dSJacob Faibussowitsch   PetscCall(PetscFree(slice->ghosts));
2029566063dSJacob Faibussowitsch   if (slice->dfill) PetscCall(PetscFree3(slice->dfill, slice->dfill->i, slice->dfill->j));
2039566063dSJacob Faibussowitsch   if (slice->ofill) PetscCall(PetscFree3(slice->ofill, slice->ofill->i, slice->ofill->j));
204435a35e8SMatthew G Knepley   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
2059566063dSJacob Faibussowitsch   PetscCall(PetscFree(slice));
2063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20747c6ae99SBarry Smith }
20847c6ae99SBarry Smith 
209d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Sliced(DM dm, Vec *gvec)
210d71ae5a4SJacob Faibussowitsch {
21147c6ae99SBarry Smith   DM_Sliced *slice = (DM_Sliced *)dm->data;
21247c6ae99SBarry Smith 
21347c6ae99SBarry Smith   PetscFunctionBegin;
21447c6ae99SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21547c6ae99SBarry Smith   PetscValidPointer(gvec, 2);
216ea78f98cSLisandro Dalcin   *gvec = NULL;
2179566063dSJacob Faibussowitsch   PetscCall(VecCreateGhostBlock(PetscObjectComm((PetscObject)dm), slice->bs, slice->n * slice->bs, PETSC_DETERMINE, slice->Nghosts, slice->ghosts, gvec));
2189566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*gvec, dm));
2193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22047c6ae99SBarry Smith }
22147c6ae99SBarry Smith 
222d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGlobalToLocalBegin_Sliced(DM da, Vec g, InsertMode mode, Vec l)
223d71ae5a4SJacob Faibussowitsch {
2243efe6655SBarry Smith   PetscBool flg;
2253efe6655SBarry Smith 
2263efe6655SBarry Smith   PetscFunctionBegin;
2279566063dSJacob Faibussowitsch   PetscCall(VecGhostIsLocalForm(g, l, &flg));
22828b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Local vector is not local form of global vector");
2299566063dSJacob Faibussowitsch   PetscCall(VecGhostUpdateEnd(g, mode, SCATTER_FORWARD));
2309566063dSJacob Faibussowitsch   PetscCall(VecGhostUpdateBegin(g, mode, SCATTER_FORWARD));
2313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2323efe6655SBarry Smith }
2333efe6655SBarry Smith 
234d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGlobalToLocalEnd_Sliced(DM da, Vec g, InsertMode mode, Vec l)
235d71ae5a4SJacob Faibussowitsch {
2363efe6655SBarry Smith   PetscBool flg;
2373efe6655SBarry Smith 
2383efe6655SBarry Smith   PetscFunctionBegin;
2399566063dSJacob Faibussowitsch   PetscCall(VecGhostIsLocalForm(g, l, &flg));
24028b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Local vector is not local form of global vector");
2419566063dSJacob Faibussowitsch   PetscCall(VecGhostUpdateEnd(g, mode, SCATTER_FORWARD));
2423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2433efe6655SBarry Smith }
2443efe6655SBarry Smith 
2453e0de288SBarry Smith /*MC
246*2fe279fdSBarry Smith    DMSLICED = "sliced" - A `DM` object that is used to manage data for a general graph. Uses `VecCreateGhost()` ghosted vectors for storing the fields
2473e0de288SBarry Smith 
248*2fe279fdSBarry Smith    See `DMCreateSliced()` for details.
2493e0de288SBarry Smith 
2503e0de288SBarry Smith   Level: intermediate
2513e0de288SBarry Smith 
252db781477SPatrick Sanan .seealso: `DMType`, `DMCOMPOSITE`, `DMCreateSliced()`, `DMCreate()`
2533e0de288SBarry Smith M*/
2543e0de288SBarry Smith 
255d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Sliced(DM p)
256d71ae5a4SJacob Faibussowitsch {
257a4121054SBarry Smith   DM_Sliced *slice;
258a4121054SBarry Smith 
259a4121054SBarry Smith   PetscFunctionBegin;
2604dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&slice));
261a4121054SBarry Smith   p->data = slice;
262a4121054SBarry Smith 
263a4121054SBarry Smith   p->ops->createglobalvector = DMCreateGlobalVector_Sliced;
26425296bd5SBarry Smith   p->ops->creatematrix       = DMCreateMatrix_Sliced;
2653efe6655SBarry Smith   p->ops->globaltolocalbegin = DMGlobalToLocalBegin_Sliced;
2663efe6655SBarry Smith   p->ops->globaltolocalend   = DMGlobalToLocalEnd_Sliced;
267a4121054SBarry Smith   p->ops->destroy            = DMDestroy_Sliced;
2683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
269a4121054SBarry Smith }
270a4121054SBarry Smith 
27147c6ae99SBarry Smith /*@C
27220f4b53cSBarry Smith     DMSlicedCreate - Creates a `DM` object, used to manage data for a unstructured problem
27347c6ae99SBarry Smith 
274d083f849SBarry Smith     Collective
2750c010503SBarry Smith 
276d8d19677SJose E. Roman     Input Parameters:
2773efe6655SBarry Smith +   comm - the processors that will share the global vector
2783efe6655SBarry Smith .   bs - the block size
2793efe6655SBarry Smith .   nlocal - number of vector entries on this process
2803efe6655SBarry Smith .   Nghosts - number of ghost points needed on this process
2813efe6655SBarry Smith .   ghosts - global indices of all ghost points for this process
2823efe6655SBarry Smith .   d_nnz - matrix preallocation information representing coupling within this process
2833efe6655SBarry Smith -   o_nnz - matrix preallocation information representing coupling between this process and other processes
2840c010503SBarry Smith 
285*2fe279fdSBarry Smith     Output Parameter:
2860c010503SBarry Smith .   slice - the slice object
2870c010503SBarry Smith 
28820f4b53cSBarry Smith     Level: advanced
28920f4b53cSBarry Smith 
2903efe6655SBarry Smith     Notes:
29120f4b53cSBarry Smith         This `DM` does not support `DMCreateLocalVector()`, `DMGlobalToLocalBegin()`, and `DMGlobalToLocalEnd()` instead one directly uses
29220f4b53cSBarry Smith         `VecGhostGetLocalForm()` and `VecGhostRestoreLocalForm()` to access the local representation and `VecGhostUpdateBegin()` and `VecGhostUpdateEnd()` to update
2933efe6655SBarry Smith         the ghost points.
2943efe6655SBarry Smith 
29520f4b53cSBarry Smith         One can use `DMGlobalToLocalBegin()`, and `DMGlobalToLocalEnd()` instead of `VecGhostUpdateBegin()` and `VecGhostUpdateEnd()`.
2960c010503SBarry Smith 
297*2fe279fdSBarry Smith .seealso: `DM`, `DMSLICED`, `DMDestroy()`, `DMCreateGlobalVector()`, `DMSetType()`, `DMSLICED`, `DMSlicedSetGhosts()`, `DMSlicedSetPreallocation()`,
298*2fe279fdSBarry Smith           `VecGhostUpdateBegin()`, `VecGhostUpdateEnd()`,
299db781477SPatrick Sanan           `VecGhostGetLocalForm()`, `VecGhostRestoreLocalForm()`
3000c010503SBarry Smith @*/
301d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSlicedCreate(MPI_Comm comm, PetscInt bs, PetscInt nlocal, PetscInt Nghosts, const PetscInt ghosts[], const PetscInt d_nnz[], const PetscInt o_nnz[], DM *dm)
302d71ae5a4SJacob Faibussowitsch {
3030c010503SBarry Smith   PetscFunctionBegin;
304064a246eSJacob Faibussowitsch   PetscValidPointer(dm, 8);
3059566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
3069566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMSLICED));
3079566063dSJacob Faibussowitsch   PetscCall(DMSlicedSetGhosts(*dm, bs, nlocal, Nghosts, ghosts));
3081baa6e33SBarry Smith   if (d_nnz) PetscCall(DMSlicedSetPreallocation(*dm, 0, d_nnz, 0, o_nnz));
3093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3100c010503SBarry Smith }
311