PETSc currently provides two basic vector types: sequential and parallel
(MPI based). To create a sequential vector with m components,
one can
use the command
ierr = VecCreateSeq(PETSC_COMM_SELF,int m,Vec *x);To create a parallel vector one can either specify the number of components that will be stored on each processor or let PETSc decide. The command
ierr = VecCreateMPI(MPI_Comm comm,int m,int M,Vec *x);creates a vector that is distributed over all processors in the communicator, comm, where m indicates the number of components to store on the local processor, and M is the total number of vector components. Either the local or global dimension, but not both, can be set to PETSC_DECIDE to indicate that PETSc should determine it. More generally, one can use the routines
ierr = VecCreate(MPI_Comm comm,int m,int M,Vec *v); ierr = VecSetFromOptions(v);which automatically generates the appropriate vector type (sequential or parallel) over all processors in comm. The option -vec_type mpi can be used in conjunction with VecCreate() and VecSetFromOptions() to specify the use of MPI vectors even for the uniprocessor case.
We emphasize that all processors in comm must call the vector creation routines, since these routines are collective over all processors in the communicator. If you are not familar with MPI communicators, see the discussion in Section Writing PETSc Programs on page Writing PETSc Programs . In addition, if a sequence of VecCreateXXX() routines is used, they must be called in the same order on each processor in the communicator.
One can assign a single value to all components of a vector with the
command
ierr = VecSet(Scalar *value,Vec x);Assigning values to individual components of the vector is more complicated, in order to make it possible to write efficient parallel code. Assigning a set of components is a two-step process: one first calls
ierr = VecSetValues(Vec x,int n,int *indices,Scalar *values,INSERT_VALUES);any number of times on any or all of the processors. The argument n gives the number of components being set in this insertion. The integer array indices contains the global component indices, and values is the array of values to be inserted. Any processor can set any components of the vector; PETSc insures that they are automatically stored in the correct location. Once all of the values have been inserted with VecSetValues(), one must call
ierr = VecAssemblyBegin(Vec x);followed by
ierr = VecAssemblyEnd(Vec x);to perform any needed message passing of nonlocal components. In order to allow the overlap of communication and calculation, the user's code can perform any series of other actions between these two calls while the messages are in transition.
Example usage of VecSetValues() may be found in src/vec/examples/tutorials/ex2.c or ex2f.F
Often, rather than inserting elements in a vector, one may wish to
add values. This process
is also done with the command
ierr = VecSetValues(Vec x,int n,int *indices, Scalar *values,ADD_VALUES);Again one must call the assembly routines VecAssemblyBegin() and VecAssemblyEnd() after all of the values have been added. Note that addition and insertion calls to VecSetValues() cannot be mixed. Instead, one must add and insert vector elements in phases, with intervening calls to the assembly routines. This phased assembly procedure overcomes the nondeterministic behavior that would occur if two different processors generated values for the same location, with one processor adding while the other is inserting its value. (In this case the addition and insertion actions could be performed in either order, thus resulting in different values at the particular location. Since PETSc does not allow the simultaneous use of INSERT_VALUES and ADD_VALUES this nondeterministic behavior will not occur in PETSc.)
There is no routine called VecGetValues(), since we provide an alternative method for extracting some components of a vector using the vector scatter routines. See Section Scatters and Gathers for details; see also below for VecGetArray().
One can examine a vector with the command
ierr = VecView(Vec x,Viewer v);To print the vector to the screen, one can use the viewer VIEWER_STDOUT_WORLD, which ensures that parallel vectors are printed correctly to stdout. The viewer VIEWER_STDOUT_SELF can be employed if the user does not care in what order the individual processors print their segments of the vector. To display the vector in an X-window, one can use the default X-windows viewer VIEWER_DRAW_WORLD, or one can create a viewer with the routine ViewerDrawOpenX(). A variety of viewers are discussed further in Section Viewers: Looking at PETSc Objects .
To create a new vector of the same format as an existing vector, one uses
the command
ierr = VecDuplicate(Vec old,Vec *new);To create several new vectors of the same format as an existing vector, one uses the command
ierr = VecDuplicateVecs(Vec old,int n,Vec **new);This routine creates an array of pointers to vectors. The two routines are very useful because they allow one to write library code that does not depend on the particular format of the vectors being used. Instead, the subroutines can automatically correctly create work vectors based on the specified existing vector. As discussed in Section Duplicating Multiple Vectors , the Fortran interface for VecDuplicateVecs() differs slightly.
When a vector is no longer needed, it should be destroyed with the
command
ierr = VecDestroy(Vec x);To destroy an array of vectors, one should use the command
ierr = VecDestroyVecs(Vec *vecs,int n);Note that the Fortran interface for VecDestroyVecs() differs slightly, as described in Section Duplicating Multiple Vectors .
It is also possible to create vectors that use an array provided by the user,
rather than having PETSc internally allocate the array space.
Such vectors can be created with the routines
ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,int m,Scalar *array,Vec *x);and
ierr = VecCreateMPIWithArray(MPI_Comm comm,int m,int M,,Scalar *array,Vec *x);Note that here one must provide the value m, it cannot be PETSC_DECIDE and the user is responsible for providing enough space in the array; m*sizeof(Scalar).