Beruflich Dokumente
Kultur Dokumente
Vec x;
The structure must be declared and created using one of the creation routines before it is
used. Vector should be destroyed after it is no longer needed.
Creation routines do not set any values of vector's elements. This can be done later using
functions described in section 'Setting values'. Also, PETSc is responsible for allocating
memory
for storing values.
Creation
This routine creates a sequential (residing on one process only) vector x of size m.
Communicator comm should be MPI_COMM_SELF.
Vec x;
VecCreateSeq(MPI_COMM_SELF, X_SIZE, &x);
This routine creates a vector over an MPI communicator comm. The vector will be distributed
among processes belonging to comm. M is the vector size, and m is the number of vector
elements to be stored on current process (the one making the call). The programmer may
order PETSc to determine m or M, but not both (use PETSC_DECIDE as argument).
If local size is to be computed automatically, PETSc will distribute the vector with an equal
(or as close as possible) number of elements on each process. It can later be found using:
In both cases size will contain the needed value. These two routines are not collective.
Example
Vec x;
This sets the vector type, type equal to VECSEQ sets sequential type, VECMPI sets the
parallel type.
sets vector local and global size, PETSC_DECIDE can be used as in above routines. The
vector is now created and ready to use (set or copy values, assemble).
Example
VecCreate(PETSC_COMM_WORLD, &x);
VecSetType(x, VECMPI);
VecSetSizes(x, PETSC_DECIDE, X_SIZE);
Creation by Copying
Another way of creating a vector is to use an existing one. To create a vector with parameters
based on another one use
This copies the structure and all attributes of v to the new vector newvec, but does not copy
the values.
This routine creates an array of m vectors which are copies of vector v. Again, values are not
copied.
Example
Vec x;
VecCreateMPI(PETSC_COMM_WORLD, PETSC_DECIDE, X_SIZE, &x);
Vec y;
// y will have the same properties as x, values will not be copied
VecDuplicate(x, &y);
Destruction
VecDestroy(Vec v);
This routine should be used to destroy an array of vectors previously created with
VecDuplicateVecs.
Example
// Assume the vectors were created as in previous example
VecDestroy(x);
VecDestroy(y);
VecDestroyVecs(z_array, Z_ARRAY_SIZE);
Setting values
x - vector to be modified
y - array of values to be inserted
ix - destination indices of values in y
ni - number of values in y
mode - two possible values: INSERT_VALUES causes the values to be copied into the
vector, ADD_VALUES adds values to existing ones
After the VecSet or VecSetValues routines are called, the vector assembly phase should be
executed:
VecAssemblyBegin(Vec x);
VecAssemblyEnd(Vec x);
The programmer may call other routines between these two calls. Any number of
VecSetValues calls can be executed on a vector using both modes of insertion, but before
different mode than in previous call is used, assembly phase must be executed.
Example
Vec x;
VecCreateMPI(PETSC_COMM_WORLD, PETSC_DECIDE, X_SIZE, &x);
This inserts value at position row into x. Depending on mode, value is inserted (mode is
INSERT_VALUES) or added to existing one (ADD_VALUES). Rules concerning assembly
phase are the same as in the case of VecSetValues.
Example
Vec x;
VecCreateMPI(PETSC_COMM_WORLD, PETSC_DECIDE, X_SIZE, &x);
If it's necessary for a vector to have the same values as another one, the programmer should
use:
This executes yi = xi. Types of vectors (sequential or parallel) don't have to match.
Accessing values
In order to read values of a vector v the programmer should use the following routine:
The argument array should be an address of a pointer, which will point to an array of
elements owned by the process. When possible, PETSc does not copy any values, just sets the
pointer to an existing array. After calling this routine, elements can be accessed like a
standard array. Note that the process can only access values stored locally.
Changing values in the array takes immediate effect - since this is the actual array used by
vector object to store values, they can be read/set directly.
to free any resources that were allocated. v is the vector of which elements are in the array,
and array is the pointer acquired with VecGetArray.
If the vector has been created so that PETSc automatically assigns elements to processes, it
may be necessary to know the range of elements stored locally. The following can be used:
Example
Vec x;
VecCreateMPI(PETSC_COMM_WORLD, PETSC_DECIDE, X_SIZE, &x);
int x_loc_size;
VecGetLocalSize(x, &x_loc_size);
VECTOR OPERATIONS
Vectors in the following routines do not have to have matching types.
Norm
This routine computes the norm of x, where type is one of the following:
NORM_1 r = Σi |xi|
NORM_2 r = (Σixi2)1/2
NORM_INFINITY r = maxi |xi|
Dot product
r = xTy
It's possible to compute the dot product of many pairs of vectors at once:
Multiplication
Key to the names: AX- multiplication (a*x, a is a scalar) XPY - x+y, y is usually the result,
for example: VecAXPY is "y = ax + y".
Other
VecScale(Vec x, PetscScalar a) x = ax
VECTOR PRINTING
Vector contents can be printed/written manually (after gaining access to the array), but it's
often useful to use PETSc built-in printing routines, for example
This routine writes vector vec contents where the viewer object defines.
Vec x;
/* Create vector and use it */
VecView(x, PETSC_VIEWER_STDOUT_WORLD);
In this case, the vector is sent to the first process (if necessary) and printed onto the standard
output. Values of elements are printed; also processes that own the vector segment (element
group) are printed at the beginning of each segment.
Another way is to create an ASCII viewer associated with a file. Writing to it will result in
information written to the designated file. Use the following:
This routine is collective. The argument comm is the MPI communicator containing
processes which will be using the viewer, name is the name of the file to which information
will be printed and viewer is the viewer object we want to create to be used later.
Example
Viewer viewer;
PetscViewerASCIIOpen(PETSC_COMM_WORLD, "outfile.txt", &viewer);
Vec x;
The way which the vector is printed to the file can be decided by setting the viewer format:
This routine sets the format for printing operations in the given viewer. Some of the possible
format values are:
There are more formats, but their output does not differ from those shown in the case of
vectors.
Examples
The following are effects of printing a sample 10-element vector distributed among 3
processes.
Process [0]
0
2
4
6
Process [1]
8
10
12
Process [2]
14
16
18
Process [0]
0
2
4
6
Process [1]
8
10
12
Process [2]
14
16
18
Process [0]
0: 0
1: 2
2: 4
3: 6
Process [1]
4: 8
5: 10
6: 12
Process [2]
7: 14
8: 16
9: 18
Vec_0 = [
0.0000000000000000e+00
2.0000000000000000e+00
4.0000000000000000e+00
6.0000000000000000e+00
8.0000000000000000e+00
1.0000000000000000e+01
1.2000000000000000e+01
1.4000000000000000e+01
1.6000000000000000e+01
1.8000000000000000e+01
];
Any text can be printed to the viewer, just like printf writes to the standard output, using:
The first argument is the viewer, and others are as in the case of printf. Only the first process
in the communicator can print this way, calls on others have no effect.
PetscViewerDestroy(PetscViewer viewer);
10
0.5
1
1.5
2
2.5
3
3.5
4
4.5
5
The first value is the number of elements and others are element values. Values appear in the
same order they are in the vector. Values are in separate lines (the newline '\n' is the
separator).
We will load the vector on one process (the file resides on one machine only), distribute it
among processes and print the content (and some other information) on each process. Number
of processes and length of the vector are assumed not to be known (length must be read from
file at runtime).
Note that we first read the vector length and distribute it using MPI_Bcast, and then create
the vector, as we want PETSc to determine the local size.
We create the vector using VecCreateMPI. Another way – separate steps – is shown in the
code, commented out, which allows the user to set the vector type using database options..
Additionally, VecView was used to show how the vector is displayed by the standard PETSc
function. The vector is sent to one process and only that process writes the results (when using
PETSC_VIEWER_STDOUT_WORLD as second argument).
#include "petscvec.h"
#include <stdio.h>
#include <stdlib.h>
#undef __FUNCT__
#define __FUNCT__ "main"
int main(int argc, char **args)
{
/* Number of processes and current process rank */
int size, rank;
/* Vector declaration */
Vec v;
int i;
/*
* Process 0 sends vector size to all other processes
* and the rest receives it.
* We assume that PetscInt is the standard int (default behaviour),
* so we can cast safely.
*/
int send_vsize = (int) v_size;
MPI_Bcast(&send_vsize, 1, MPI_INT, 0, PETSC_COMM_WORLD);
v_size = (PetscInt) send_vsize;
/*
* Vector creation
* We decide the vector type (parallel) immediately
*/
/*
* Vector creation, separate steps
* We decide about vector attributes in separate steps.
*/
/*
ierr = VecCreate(PETSC_COMM_WORLD, &v); CHKERRQ(ierr);
ierr = VecSetType(v, VECMPI); CHKERRQ(ierr);
ierr = VecSetSizes(v, PETSC_DECIDE, v_size); CHKERRQ(ierr);
*/
/*
* Root process reads element values from file and sets them,
* other processes do nothing - they will receive their values
* automatically later.
*/
if (rank==0)
{
for (i = 0 ; i<v_size ; i++)
{
fscanf(vecf, "%lg\n", &val);
ierr = VecSetValue(v, i, val, INSERT_VALUES); CHKERRQ(ierr);
}
}
/* Read the size of locally owned vector part, and its range */
ierr = VecGetOwnershipRange(v, &v_loc_start, &v_loc_end); CHKERRQ(ierr);
ierr = VecGetLocalSize(v, &v_loc_size); CHKERRQ(ierr);
/*
* Print information about vector to standard output,
* each process reports its own data. Messages from different processes
* do not get mixed.
*/
PetscSynchronizedPrintf(PETSC_COMM_WORLD, "Process %d:\n", rank);
PetscSynchronizedPrintf(PETSC_COMM_WORLD, "v size = %d\n", v_size);
PetscSynchronizedPrintf(PETSC_COMM_WORLD, "v local size = %d\n", v_loc_size);
PetscSynchronizedPrintf(PETSC_COMM_WORLD, "v local start of range = %d\n",
v_loc_start);
PetscSynchronizedPrintf(PETSC_COMM_WORLD, "v local end of range = %d\n",
v_loc_end);
PetscSynchronizedPrintf(PETSC_COMM_WORLD, "\n");
PetscSynchronizedFlush(PETSC_COMM_WORLD);
return 0;
}
The sample output from the program is shown below. The program was run on 3 processes.
Process 0:
v size = 10
v local size = 4
v local start of range = 0
v local end of range = 4
v[0] = 0.5
v[1] = 1
v[2] = 1.5 highest index + 1
v[3] = 2
Process 1:
v size = 10
v local size = 3
v local start of range = 4
v local end of range = 7 highest index
v[4] = 2.5
v[5] = 3
v[6] = 3.5
Process 2:
v size = 10
v local size = 3
v local start of range = 7
v local end of range = 10
v[7] = 4
v[8] = 4.5
v[9] = 5
Process [0]
0.5
1
1.5
2
Process [1]
2.5 VecView(v, PETSC_VIEWER_STDOUT_WORLD) output
3
3.5
Process [2]
4
4.5
5