A FEM field specifies scalar or vector values for the features of an FEM mesh. These can be either the nodes (nodal fields), elements (element fields), or element integration points (sub-element fields). As such, FEM fields provide a way to augment the mesh to store application-specific quantities, and are typically used to bind properties of FEM materials that need to vary over the domain (Section 7.5).
To evaluate getValue(p) at an arbitrary point , the field finds the FEM element containing (or nearest to , if is outside the FEM mesh), and either interpolates the value from the surrounding nodes (nodal fields), uses the element value directly (element fields), or interpolates from the integration point values (sub-element fields).
When finding a FEM field value at a point , getValue(p) is evaluated with respect to the FEM model’s current spatial position, as opposed to its rest position.
FEM fields maintain a default value which describes the value at features for which values are not explicitly set. If unspecified, the default value itself is zero.
In the remainder of this section, it is assumed that vector fields are constructed using fixed-size vectors or matrices, such as Vector3d or Matrix3d. However, it is also possible to construct fields using VectorNd or MatrixNd, with the aid of special wrapper classes, as described in Section 7.4. That section also details a convenience wrapper class for Vector3d.
The three field types are now described in detail.
Implemented by ScalarNodalField, VectorNodalField<T>, or subclasses of the latter, nodal fields specify their values at the nodes of an FEM mesh. They can be created with constructors such as
where fem is the associated FEM model, defaultValue is the default value, and name is a component name. For vector fields, the maspack.matrix.VectorObject type is parameterized by T, and type gives its actual class type (e.g., Vector3d.class).
Once the grid has been created, values can be queried and set at the nodes using methods such as
Here nodeNum refers to an FEM node’s number (which can be obtained using node.getNumber()). Numbers are used instead of indices to identity FEM nodes and elements because they are guaranteed to be persistent in case of mesh editing, and will remain unchanged as long as the node or element is not removed from the FEM model. Note that values don’t need to be set at all nodes, and set values can be unset using the clear methods. For nodes with no value set, the getValue() methods will return the default value.
As a simple example, the following code fragment constructs a ScalarNodalField for an FEM model fem that describes stiffness values at every node of an FEM:
As noted earlier, FEM fields should be stored in the fields list of the associated FEM model.
Another example shows the creation of a field of 3D direction vectors:
When creating a vector field, the constructor needs the class type of the field’s VectorObject. However, for the special case of Vector3d, one may also use the convenience wrapper class Vector3dNodalField, described in Section 7.4.
Implemented by ScalarElementField, VectorElementField<T>, or subclasses of the latter, element fields specify their values at the elements of an FEM mesh, and these values are assumed to be constant within the element. To evaluate getValue(p), the field finds the containing (or nearest) element for , and then returns the value for that element.
Because values are assume to be constant within each element, element fields are inherently discontinuous across element boundaries.
The constructors for element fields are analogous to those for nodal fields:
and the methods for setting values at elements are similar as well:
The elements associated with an element field can be either volume or shell elements, which are stored in the FEM component lists elements and shellElements, respectively. Since volume and shell elements may share element numbers, the separate methods getElementValue() and getShellElementValue() are used to access values by element number.
The following code fragment constructs a VectorElementField based on Vector2d that stores a 2D coordinate value at all regular and shell elements:
Implemented by ScalarSubElemField, VectorSubElemField<T>, or subclasses of the latter, sub-element fields specify their values at the integration points within each element of an FEM mesh. These fields are used when we need precisely computed information at each of the element’s integration points, and we can’t assume that nodal interpolation will give an accurate enough approximation.
To evaluate getValue(p), the field finds the containing (or nearest) element for , extrapolating the integration point values back to the nodes, and then using nodal interpolation.
Constructors are similar to those for element fields:
Value accessors are also similar, except that an additional argument k is required to specify the index of the integration point:
The integration point index k should be in the range 0 to , where is the total number of integration points for the element in question and can be queried by the method numAllIntegrationPoints().
The total number of integration points includes both the regular integration point as well as the warping point, which is located at the element center, is indexed by , and is used for corotated linear materials. If a SubElemField is being using to supply mesh-varying values to one of the linear material parameters (Section 7.5), then it is important to supply values at the warping point.
The example below shows the construction of a ScalarSubElemField:
First, the field is instantiated with the name "modulus". The code then iterates first through the FEM elements, and then through each element’s integration points, computing values appropriate to each one. A list of each element’s integration points is returned by e.getAllIntegrationPoints(). Having access to the actual integration points is useful in case information about them is needed to compute the field values. In particular, if it is necessary to obtain an integration point’s rest or current (spatial) position, these can be queried as follows:
The regular integration points, excluding the warping point, can be queried using getIntegrationPoints() and numIntegrationPoints() instead of getAllIntegrationPoints() and numAllIntegrationPoints().