- userFuncUpdater
userFuncUpdater¶
Works with VSimBase, VSimEM, VSimPD, VSimPA, and VSimVE licenses.
Sets field values to the result of a user-given function.
The FieldUpdater of kind = userFuncUpdater
is a very flexible updater
that sets a field to the result of a user-given <Expression>
(see expression). The expression
takes as arguments field values and spatial positions, as
well as time and time step.
The userFuncUpdater can be used to do many different things; to understand how it works in some simple cases, it may be easier to skip to the examples at the end of this section.
The userFuncUpdater places iterators at the first cell of each read/writeField. The iterators are then moved from cell to cell; each iterator keeps track of its position and the field value at that position. As the iterators are collectively moved from cell to cell, an update is performed at each cell. An iterator knows its cell index, as well as the exact spatial location of the field value corresponding to that cell index (taking into account the field offset; e.g., the Yee electric field is usually located at the center-edges of a cell).
A userFuncUpdater has one iterator for every writeField, and one for every readField. The userFuncUpdater sets the field-values through the iterators on its writeFields according to a function of, among other things, the iterator positions, and the values of the readFields at their iterators. It then moves all the iterators by one cell and does the same thing, etc.
A userFuncUpdater can also has one or more readScalars. These scalars are read only. They can be used as variables in the function expression. userFuncUpdater can not update any scalars. To updater a scalar, one should use userFuncScalarUpdater.
A userFuncUpdater specifies a function (an Expression) that takes as arguments the values of the read fields, the positions of the read- and write-Field iterators, as well as the time and time step; and the function returns a vector with one value for each writeField (at each cell, each writeField is set to the corresponding value).
userFuncUpdater Parameters¶
The userFuncUpdater
takes the lowerBounds
and
upperBounds
parameters of FieldUpdater, as well as
the following parameters:
- readFields (optional string vector, default = [])
The names of the fields to read. A field name can be repeated if multiple iterators are used from a single field.
- readScalars (optional string vector, default = [])
The names of the scalars to read. A scalar name can be directly used as a variable in a userFunc expression.
- writeFields (required string vector)
The names of the fields to write. A field name can be repeated if multiple iterators are used from a single field.
- readComponents (optional integer vector)
The component used for each readField. If any
readFields
are specified, this must be as well, and have the same number of elements asreadFields
.
- writeComponents (required integer vector)
The component used for each writeField. This must have the same length as
writeFields
.
- readItersShiftInX (optional integer vector)
This has the same length as
readFields
; by default it is all zeros. With this specified, eachreadFields
iterator is shifted by the corresponding number of cells in the \(x\) direction. For example,readItersShiftInX = [1 0]
will shift the iterators on the firstreadFields
by one cell in the \(+x\) direction, and won’t shift the iterators on the secondreadFields
in \(x\).
- readItersShiftInY (optional integer vector)
Similar to
readItersShiftInX
, but shifts iterators in \(y\). If the \(y\) direction is not simulated, this is ignored.
- readItersShiftInZ (optional integer vector)
Similar to
readItersShiftInX
, but shifts iterators in \(z\). If the \(z\) direction is not simulated, this is ignored.
- readFieldVarNames (optional string vector)
The variable names given to the value of each field–this is how the field values will be referenced in the Expression. If any
readFields
are specified, this must be as well, and have the same number of elements asreadFields
. Each name must be unique; some names are forbidden, such ast
anddt
andn
.
- readFieldPosVariables (optional string vector)
The names given to the variables representing the position of the corresponding readField value; each such variable is an \(N\)-dimensional vector, where \(N\) is the dimension of the simulation. However,
notUsed
means that the corresponding field position is not used in the Expression; ignoring a position in this way can speed up computation. Ifpos
is the variable name given to a certain readField, then the variablepos
(that appears in the Expression) will be an \(N\)-dimensional vector. For example, in an expression, the \(x\) position would be accessed byselect(pos, 0)
and the \(y\) position (in 2D or 3D simulation) byselect(pos, 1)
. If given, this parameter must be a vector with the same length asreadFields
. If not given, all elements are set tonotUsed
.
- writeFieldPosVariables (optional string vector)
Analogous to
readFieldPosVariables
, but forwriteFields
.
- updateFunction (required parameter block)
A parameter block of type Expression and name
updateFunction
is required to define the function used to update thewriteFields
. This block takes the same parameters as an expression UserFunc, except forInput
blocks and theinputOrder
parameter. The input variables for theexpression
are defined by the above parameters, so they are not to be specified in theupdateFunction
block. In addition, the expression can take the following input valiables:t
:The simulation time (actually, the time to which the updater been told to update its writeFields; c.f. toDtFrac in a MultiField UpdateStep).
dt
:The most recent time step (\(\Delta t\)).
n
:The current simulation step (an integer).
(These names are reserved—they cannot be used as variable names:
readFieldVarNames
,readFieldPosVariables
, orwriteFieldPosVariables
.)The Expression must return a vector with the same length as the number of writeFields—each writeField value will be set to the corresponding component of the return vector.
userFuncUpdater Examples¶
Here is a userFuncUpdater to set a scalar field \(F\) to a function \(f(x,y,z,t)\):
<FieldUpdater setF>
kind = userFuncUpdater
lowerBounds = [0 0 0]
upperBounds = [NX NY NZ]
writeFields = [F]
writeComponents = [0]
writeFieldPosVariables = [Fpos] # just a choice of name
maxNumEvals = 64
<Expression updateFunction>
$ X = select(Fpos, 0) # makes the function more readable
$ Y = select(Fpos, 1)
expression = sin(kx * X + ky * Y + kz * select(Fpos, 2) - omega * t)
<Term kx>
kind = constant
value = [10.]
</Term>
<Term ky>
kind = constant
value = [20.]
</Term>
<Term kz>
kind = constant
value = [3.]
</Term>
<Term omega>
kind = constant
value = [ $ LIGHTSPEED * math.sqrt(10^2 + 20^2 + 3^2) $ ]
</Term>
</Expression>
</FieldUpdater>
The above could be done equally well with a STFuncUpdater. However, setting a vector field \(\mathbf{F}\) to a field can be done better with a userFuncUpdater, since it can evaluate the function at a different position for each component:
<FieldUpdater setF>
kind = userFuncUpdater
lowerBounds = [0 0 0]
upperBounds = [NX NY NZ]
writeFields = [F F F]
writeComponents = [0 1 2]
writeFieldPosVariables = [FxPos FyPos FzPos]
maxNumEvals = 64
<Expression updateFunction>
kind = expression
$ XPHASE = kx * select(FxPos,0) + ky * select(FxPos, 1) + kz * select(FxPos, 2)
$ YPHASE = kx * select(FyPos,0) + ky * select(FyPos, 1) + kz * select(FyPos, 2)
$ ZPHASE = kx * select(FzPos,0) + ky * select(FzPos, 1) + kz * select(FzPos, 2)
expression = sin( vector(XPHASE, YPHASE, ZPHASE) - omega * t)
<Term kx>
kind = constant
value = [10.]
</Term>
<Term ky>
kind = constant
value = [20.]
</Term>
<Term kz>
kind = constant
value = [3.]
</Term>
<Term omega>
kind = constant
value = [ $ LIGHTSPEED * math.sqrt(10^2 + 20^2 + 3^2) $ ]
</Term>
</Expression>
</FieldUpdater>
Here is a userFuncUpdater that multiplies a 3-vector field \(\mathbf{G}\) by \(\Delta t\) and adds it to a 3-vector field \(\mathbf{F}\) (i.e., \(\mathbf{F}\mapsto\mathbf{F} + \mathbf{G}\Delta t\)):
<FieldUpdater addGdtToF>
kind = userFuncUpdater
lowerBounds = [0 0 0]
upperBounds = [NX NY NZ]
readFields = [F F F G G G]
readComponents = [0 1 2 0 1 2]
readFieldVarNames = [Fx Fy Fz Gx Gy Gz]
writeFields = [F F F]
writeComponents = [0 1 2]
maxNumEvals = 64
<Expression updateFunction>
expression = vector(Fx, Fy, Fz) + dt * vector(Gx, Gy, Gz)
</Expression>
</FieldUpdater>
Here is an example of a userFuncUpdater that uses the values of a History to perform its update (see historyFunc):
# A field updater that sets field values to the x-index of the cell
# with the (most recent) maximum value of a field, by using a History
# that finds that x-index. Of course, one could also use a History
# that calculates voltage to use as feedback.
<FieldUpdater setFieldToIndexOfMax>
kind = userFuncUpdater
lowerBounds = [0 0 0]
upperBounds = [2 2 2]
writeFields = [G]
writeComponents = [0]
<Expression updateFunction>
# Presumably the input file defines a <History max> that records
# the location of the maximum field value;
# This HistoryFunc gets the x-value of that location.
<UserFunc iOfLastMax>
kind = historyFunc
index = [0] # x-index of cell
history = max
</UserFunc>
# get (1000*) x-index of cell with most recent maximum value of field F
expression = 1000 * iOfLastMax(0)
</Expression>
</FieldUpdater>