Next: , Up: Stencils   [Contents][Index]


4.2 Declaring stencil objects

A stencil declaration may not be inside a function. It can appear inside a class declaration (in which case the stencil object is a nested type).

Stencil objects are declared using the macros BZ_DECLARE_STENCIL1, BZ_DECLARE_STENCIL2, etc. The number suffix is how many arrays are involved in the stencil (in the above example, 4 arrays– P1, P2, P3, c – are used, so the macro BZ_DECLARE_STENCIL4 is invoked).

The first argument is a name for the stencil object. Subsequent arguments are names for the arrays on which the stencil operates.

After the stencil declaration, the macro BZ_END_STENCIL must appear (or the macro BZ_END_STENCIL_WITH_SHAPE, described in the next section).

In between the two macros, you can have multiple assignment statements, if/else/elseif constructs, function calls, loops, etc.

Here are some simple examples:

BZ_DECLARE_STENCIL2(smooth2D,A,B)
  A = (B(0,0) + B(0,1) + B(0,-1) + B(1,0) + B(-1,0)) / 5.0;
BZ_END_STENCIL

BZ_DECLARE_STENCIL4(acoustic2D,P1,P2,P3,c)
  A = 2 * P2 + c * (-4 * P2(0,0) + P2(0,1) + P2(0,-1) + P2(1,0) + P2(-1,0))
      - P1;
BZ_END_STENCIL

BZ_DECLARE_STENCIL8(prop2D,E1,E2,E3,M1,M2,M3,cE,cM)
  E3 = 2 * E2 + cE * Laplacian2D(E2) - E1;
  M3 = 2 * M2 + cM * Laplacian2D(M2) - M1;
BZ_END_STENCIL

BZ_DECLARE_STENCIL3(smooth2Db,A,B,c)
  if ((c > 0.0) && (c < 1.0))
    A = c * (B(0,0) + B(0,1) + B(0,-1) + B(1,0) + B(-1,0)) / 5.0
      + (1-c)*B;
  else
    A = 0;
BZ_END_STENCIL

Currently, a stencil can take up to 11 array parameters.

You can use the notation A(i,j,k) to read the element at an offset (i,j,k) from the current element. If you omit the parentheses (i.e. as in “A” then the current element is read.

You can invoke stencil operators which calculate finite differences and laplacians.

4.3 Automatic determination of stencil extent

In stencil declarations such as

BZ_DECLARE_STENCIL2(smooth2D,A,B)
  A = (B(0,0) + B(0,1) + B(0,-1) + B(1,0) + B(-1,0)) / 5.0;
BZ_END_STENCIL

Blitz++ will try to automatically determine the spatial extent of the stencil. This will usually work for stencils defined on integer or float arrays. However, the mechanism does not work well for complex-valued arrays, or arrays of user-defined types. If you get a peculiar error when you try to use a stencil, you probably need to tell Blitz++ the special extent of the stencil manually.

You do this by ending a stencil declaration with BZ_END_STENCIL_WITH_SHAPE:

BZ_DECLARE_STENCIL2(smooth2D,A,B)
  A = (B(0,0) + B(0,1) + B(0,-1) + B(1,0) + B(-1,0)) / 5.0;
BZ_END_STENCIL_WITH_SHAPE(shape(-1,-1),shape(+1,+1))

The parameters of this macro are: a TinyVector (constructed by the shape() function) containing the lower bounds of the stencil offsets, and a TinyVector containing the upper bounds. You can determine this by looking at the the terms in the stencil and finding the minimum and maximum value of each index:

      A = (B(0,  0) 
         + B(0, +1)
         + B(0, -1)
         + B(+1, 0)
         + B(-1, 0)) / 5.0;
           --------
min indices  -1, -1
max indices  +1, +1

Next: , Up: Stencils   [Contents][Index]