A linear operator can be defined as an extended matrix multiply. That is, it is a tensor product from one set of dimensions to another set of dimensions. It can sum along any number of dimensions, eliminating those dimensions. Also, it can expand any number of dimensions, adding new dimensions. Matrix multiplication is a particular case of a linear operator which sums along one dimension, and expands along another.
An operator only has three public functions
Using the summation convention, here are some familiar geophysical operations. The order of subscripts of an operator is defined by the axis mappings that the forward operator applies. e.g. maps the x axis to a v axis.
Convolution along the time axis maps the time axis to a new time axis (let us call it t'). The forward convolution operator can be defined by:
The convolution operator maps the t axis to a t' axis. The conjugate operator, a correlation, is maps the t' axis to a t axis:
The NMO modeling operator, , maps a trace from zero offset to any given offset, x.
This operator adds offset, x, dependency to the trace. In contrast the conjugate operator removes the offset dependency of the trace.
Note that this operator is applied to a single trace. It is not the same as the NMOStack operator for which the forward operation models to a range of offsets and the conjugate operation stacks over offset.
Our operators are procedural operators. That is, every operator has, at its heart, a procedure which tells it what to do with the space it is being applied to. When the operator is constructed (initialized), it is told what axes to apply itself to. At this point, it knows what axes, size, label, etc., it is expecting, and what axes it will output. Then, when the operator is applied to a space, it will automatically find the correct axes to apply itself to.
Any extra axes will merely be cycled through, applying the same operator to each index in that dimension. This ability to cycle through extra dimensions is built into the basic operator class. Any class that is derived from the base operator class inherits this ability without the author having to write any code to implement it.
In many cases the axis definitions are basic to the definition of the operator, so this strictly defined axis compatibility is necessary. e.g. a velocity analysis operator needs to know both the dimensions of the offset-time space that the forward operator should model to, and the dimensions of the velocity-time space that the conjugate operator creates.
In the current implementation you must specify all the attributes of the axes that an operator is to be applied to. This is not always necessary; a convolution operator only needs to match the axis label and sample rate. It can be applied to any length of trace stating at any initial sample. In the future we intend to implement a more liberal scheme for matching the axis definitions of operators and spaces.
Here is an example of constructing an operator. The ``floatConvolve'' operator class performs convolution as its Forward function.
\\ Declare and initialize an instance of the floatConvolve class floatConvolve op(axis,filter);Where axis is an Axis object, that defines the axis to convolve along, and filter is a that defines the filter to convolve with. Here is the code to apply this operator to a , x, to produce an output ,``result''.
floatspace result = op.Forward(x);If the x, does not have an axis that matches the axis that the operator is designed to be applied to an error will be generated at run time.