UserFunc Block

A block for functions specifed by the user

UserFuncs can be used to specify a function, e.g., as a string expression. While already very powerful and useful, UserFuncs are still an experimental feature that will require continued development, and the interfaces to them will probably change as they evolve.

A UserFunc is a vector-valued function that takes vector arguments; in general, a UserFunc can take an arbitrary number of vector arguments, and return a vector; each vector (in general) can contain any number of scalar elements.

Note

For convenience, we will often write vectors using brackets, e.g., [1.5, 2, -3, 4.1]. However, this bracket-notation is not recognized within a UserFunc expression, where a vector must be written vector(1.5,  2, -3, 4.1).

UserFuncs distinguish 3 types of scalars: float (a floating point number), integer, and boolean (0 or 1).

Note

Type information helps avoid unexpected values before any evaluation is performed; type information is never used during the evaluation itself. In other words, if the number 1 is passed to a function, the result will never depend on whether 1 is a boolean, an integer, or a float; in particular, 1.0/2.0 = 1/2 = 0.5 as far as UserFuncs are concerned.

A function that takes an integer argument will also take a boolean; similarly, a function that takes a float argument will also take an integer or a boolean. The reverse is not true: e.g., a function that takes a boolean will not take a general integer or float.

A specific UserFunc has a signature that describes the number, lengths, and types of arguments, as well as the length and types of the result. Here are the signatures of some common functions:

\[\begin{split}\begin{aligned} \sin : && ([\textrm{float}]) \rightarrow [\textrm{float}] \nonumber\\ == : && ([\textrm{float}], [\textrm{float}]) \rightarrow [\textrm{boolean}] \nonumber \\ \textrm{floor} : && ([\textrm{float}]) \rightarrow [\textrm{integer}] \nonumber \end{aligned}\end{split}\]

In these simple examples, each vector (argument or result) has only one element.

UserFuncs use 0-indexing: the first argument is argument 0; the first element of a vector has index 0.

Simple UserFuncs of kind = expression are easy to use when, for instance, they are employed in the same way as STFuncs. For example, suppose some attribute block expects a UserFunc that is a function of space and time, i.e., of scalars x, y, z, and t. Example input might be:

<OuterBlock someObjectThatNeedsAUserSpecifiedFunction>
  ...
  <UserFunc someName>
    kind = expression
    inputOrder = [t x y z]
    <Input t>
      kind = arbitraryVector
      types = [float]
    </Input>
    <Input x>
      kind = arbitraryVector
      types = [float]
    </Input>
    expression = sin(3*x) * cos(0.2*t)
  </UserFunc>
</OuterBlock>

To learn how to use UserFuncs, it might be easiest to look first at examples (such as in Local UserFuncs and Term Block), and then refer to the following explanation as needed.

Kinds of UserFuncs

There are several kinds of UserFuncs: an expression simply takes a string expression in the input file.

An expression UserFunc block must include its input signature (inputOrder and the <Input> blocks), but most other UserFuncs have only one possible input signature and therefore don’t require the input signature to be specified. (And <Expression> is like UserFuncs of kind=expression but require no signature; see expression.)

UserFuncs specified at the top-level of the input file are special because they can be called by any other UserFuncs (or <Expression>s) in the entire simulation.

Some of these kinds get their values from other simulation objects; when running parallel simulations, it is important to remember that the entire object may not be accessible to all processors. For example, a fieldFunc can in principle be used to look up a field value at any spatial location; however, each rank has access to just a part of the field—attempting to find the field value outside that range will halt the simulation. Some objects that use UserFuncs (notably cellFuncHist) offer backup-functions that can be called should the main UserFunc fail to evaluate.

UserFunc Parameters

General UserFuncs can take the following attribute:

maxNumEvals (positive integer, optional, default = 128)

The maximum number of simultaneous evaluations a function can perform (see Speed and Multiple Evaluations of UserFuncs). Increasing this number increases memory use and evaluation speed: 16–128 is recommended for kind = expression.