# MatCreateShell
Creates a new matrix of `MatType` `MATSHELL` for use with a user-defined private data storage format. 
## Synopsis
```
#include "petscmat.h" 
PetscErrorCode MatCreateShell(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt M, PetscInt N, void *ctx, Mat *A)
```
Collective


## Input Parameters

- ***comm -*** MPI communicator
- ***m -*** number of local rows (must be given)
- ***n -*** number of local columns (must be given)
- ***M -*** number of global rows (may be PETSC_DETERMINE)
- ***N -*** number of global columns (may be PETSC_DETERMINE)
- ***ctx -*** pointer to data needed by the shell matrix routines



## Output Parameter

- ***A -*** the matrix





## Usage
```none
extern PetscErrorCode mult(Mat,Vec,Vec);
```
```none
MatCreateShell(comm,m,n,M,N,ctx,&mat);
```
```none
MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
```
```none
[ Use matrix for operations that have been set ]
```
```none
MatDestroy(mat);
```


## Notes
The shell matrix type is intended to provide a simple class to use
with `KSP` (such as, for use with matrix-free methods). You should not
use the shell type if you plan to define a complete matrix class.

PETSc requires that matrices and vectors being used for certain
operations are partitioned accordingly.  For example, when
creating a shell matrix, A, that supports parallel matrix-vector
products using `MatMult`(A,x,y) the user should set the number
of local matrix rows to be the number of local elements of the
corresponding result vector, y. Note that this is information is
required for use of the matrix interface routines, even though
the shell matrix may not actually be physically partitioned.
For example,

```none
```
```none
Vec x, y
```
```none
extern PetscErrorCode mult(Mat,Vec,Vec);
```
```none
Mat A
```
```none
```
```none
VecCreateMPI(comm,PETSC_DECIDE,M,&y);
```
```none
VecCreateMPI(comm,PETSC_DECIDE,N,&x);
```
```none
VecGetLocalSize(y,&m);
```
```none
VecGetLocalSize(x,&n);
```
```none
MatCreateShell(comm,m,n,M,N,ctx,&A);
```
```none
MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
```
```none
MatMult(A,x,y);
```
```none
MatDestroy(&A);
```
```none
VecDestroy(&y);
```
```none
VecDestroy(&x);
```
```none
```

`MATSHELL` handles `MatShift()`, `MatDiagonalSet()`, `MatDiagonalScale()`, `MatAXPY()`, `MatScale()`, `MatZeroRows()` and `MatZeroRowsColumns()` internally, so these
operations cannot be overwritten unless `MatShellSetManageScalingShifts()` is called.

For rectangular matrices do all the scalings and shifts make sense?


## Developers Notes
Regarding shifting and scaling. The general form is

diag(left)(vscale*A + diag(dshift) + vshift I)diag(right)

The order you apply the operations is important. For example if you have a dshift then
apply a MatScale(s) you get s*vscale*A + s*diag(shift). But if you first scale and then shift
you get s*vscale*A + diag(shift)

A is the user provided function.

`KSP`/`PC` uses changes in the `Mat`'s "state" to decide if preconditioners need to be rebuilt: `PCSetUp()` only calls the setup() for
for the `PC` implementation if the `Mat` state has increased from the previous call. Thus to get changes in a `MATSHELL` to trigger
an update in the preconditioner you must call `MatAssemblyBegin()` and `MatAssemblyEnd()` or `PetscObjectStateIncrease`((`PetscObject`)mat);
each time the `MATSHELL` matrix has changed.

Matrix product operations (i.e. `MatMat()`, `MatTransposeMat()` etc) can be specified using `MatShellSetMatProductOperation()`

Calling `MatAssemblyBegin()`/`MatAssemblyEnd()` on a `MATSHELL` removes any previously supplied shift and scales that were provided
with `MatDiagonalSet()`, `MatShift()`, `MatScale()`, or `MatDiagonalScale()`.


## Fortran Note
To use this from Fortran with a ctx you must write an interface definition for this
function and for `MatShellGetContext()` that tells Fortran the Fortran derived data type you are passing
in as the ctx argument.


## See Also
 `MATSHELL`, `MatShellSetOperation()`, `MatHasOperation()`, `MatShellGetContext()`, `MatShellSetContext()`, `MATSHELL`, `MatShellSetManageScalingShifts()`, `MatShellSetMatProductOperation()`

## Level
advanced

## Location
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/mat/impls/shell/shell.c.html#MatCreateShell">src/mat/impls/shell/shell.c</A>

## Examples
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/mat/tutorials/ex6f.F90.html">src/mat/tutorials/ex6f.F90.html</A><BR>
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/ksp/ksp/tutorials/ex14f.F90.html">src/ksp/ksp/tutorials/ex14f.F90.html</A><BR>
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/snes/tutorials/ex36.c.html">src/snes/tutorials/ex36.c.html</A><BR>
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/ts/tutorials/ex20opt_ic.c.html">src/ts/tutorials/ex20opt_ic.c.html</A><BR>
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/ts/tutorials/ex22f_mf.F90.html">src/ts/tutorials/ex22f_mf.F90.html</A><BR>
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/tao/unconstrained/tutorials/eptorsion1.c.html">src/tao/unconstrained/tutorials/eptorsion1.c.html</A><BR>
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/tao/unconstrained/tutorials/eptorsion3.c.html">src/tao/unconstrained/tutorials/eptorsion3.c.html</A><BR>
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/tao/bound/tutorials/plate2.c.html">src/tao/bound/tutorials/plate2.c.html</A><BR>
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/tao/pde_constrained/tutorials/elliptic.c.html">src/tao/pde_constrained/tutorials/elliptic.c.html</A><BR>
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/tao/pde_constrained/tutorials/hyperbolic.c.html">src/tao/pde_constrained/tutorials/hyperbolic.c.html</A><BR>
<A HREF="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/tao/pde_constrained/tutorials/parabolic.c.html">src/tao/pde_constrained/tutorials/parabolic.c.html</A><BR>


---
[Edit on GitLab](https://gitlab.com/petsc/petsc/-/edit/release/src/mat/impls/shell/shell.c)


[Index of all Mat routines](index.md)  
[Table of Contents for all manual pages](/docs/manualpages/index.md)  
[Index of all manual pages](/docs/manualpages/singleindex.md)  
