Source/Nodes/Fields

Fields
A `Field` represents a function that outputs a value based on an arbitrary number of inputs. The inputs for a specific field evaluation are provided by a `FieldContext`.

A typical example is a field that computes a displacement vector for every vertex on a mesh based on its position. In this case the `FieldContext` is the mesh with the position attribute.

Fields can be build, composed and evaluated at run-time. They are stored in a directed tree graph data structure, whereby each node is a `FieldNode` and edges are dependencies. A `FieldNode` has an arbitrary number of inputs and at least one output. A `Field` is a specific output of a `FieldNode`. The inputs of a `FieldNode` are other fields. All fields are immutable once they are built.

There are two different types of field nodes:
 * `FieldInput`: Has no input and exactly one output. It represents an input to the entire field when it is evaluated. During evaluation, the value of this input is based on a `FieldContext`.
 * `FieldOperation`: Has an arbitrary number of field inputs and at least one output. Its main use is to compose multiple existing fields into new fields.

Given one or more fields and a `FieldContext`, the fields can be evaluated using the `FieldEvaluator` class.

Generic and Typed Fields
Most of the time, when working with fields, they have a specific type that is known at compile time. In this case, the `Field` class should be used. This class is a wrapper around a more generic `GField` class (where G stands for "generic"). A `GField` is a field whose type is only known at run-time. When converting from a `GField` to a `Field` there is a run-time assert that makes sure that the conversion is valid.