OOF2: The Manual
Name
Field — Base class for fields
Synopses
Only those methods useful when extending OOF2 are listed here.
C++ Synopsis
#include "engine/field.h"
class Field {const std::string& name() const;int ndof() const;bool is_defined(const CSubProblem* subproblem) const;bool is_active(const CSubProblem* subproblem) const;virtual DegreeOfFreedom* operator()(const FuncNode* node,
int component) const;virtual DegreeOfFreedom* operator()(const ElementFuncNodeIterator& node,
int component) const;DegreeOfFreedom* operator()(const FuncNode& node,
int component) const;DegreeOfFreedom* operator()(const ElementFuncNodeIterator& node,
const IndexP& component) const;double value(const FEMesh* mesh,
const FuncNode* node,
int component) const;double value(const FEmesh* mesh,
const ElementFuncNodeIterator& node,
int component) const;virtual double value(const FEmesh* mesh,
const Element* element,
const MasterPosition& position,
const FieldIndex& component) const;virtual double gradient(const FEmesh* mesh,
const Element* element,
const MasterPosition& position,
const FieldIndex& component,
SpaceIndex index) const;virtual ArithmeticOutputValue output(const FEMesh* mesh,
const ElementFuncNodeIterator& node) const;virtual ArithmeticOutputValue output(const FEMesh* mesh,
const FuncNode& node) const;virtual Components* components(Planarity planarity= ALL_INDICES) const;virtual Components* outOfPlaneComponents() const;virtual FieldIndex* getIndex(const std::string& name) const;
}
Python Synopsis
from ooflib.SWIG.engine.field import Field
class Field:def ndof(self)def is_defined(self, mesh)def is_active(self, mesh)def value(self, mesh, node, component)def components(self, planarity= ALL_INDICES)def outOfPlaneComponents(self)def getIndex(self, name)
Description
Field is an abstract base class for all
types of fields in OOF2. The role of fields is described in
Section 2.5.3. Like Fluxes and
Equations,
Field instances are global objects — there is one
instance for each physical field and it is shared by all
Meshes that use it. Fields store information about
the physical field (such as its name and dimension), but do not
store the actual values of the Field. That's done by a
Mesh, by using bookkeeping data from a Field.
Most of the programming interface for Fields is defined
in the base class, which is an abstract C++ class. Most of the
API is available from both C++ and Python.
Most of the Field objects encountered by OOF2 users and
extenders are actually instances of the CompoundField
class, which groups the in-plane and out-of-plane parts of a
Field, along with their time derivatives, all of which
are Fields themselves.
Field objects should only be created by
calling the Python constructors of the CompoundField subclasses. See CompoundField for the details. After a
Field has been created, it can be
retrieved in C++ or Python via the getField
function. It is not necessary to keep an explicit Python
reference to a newly created Field.
For convenience in scripts, a
variable with the Field's name referring
to the Field is defined in the main
OOF2 namespace, which is aslo used in text mode and the Console Window.
Several methods are available for computing the values of
Fields at points within an FEMesh.
-
Various versions of
Field::value()return the value of a component of aFieldat a givenNode. -
Versions of
Field::value()withElementand position arguments return the value of a field component interpolated within the givenElement. -
Field::value()returns the value of aFieldcomponent at an arbitrary position within anElement.ScalarFieldhas a version that doesn't require acomponentargument. -
Each concrete non-scalar subclass of
Fieldhas avalues()method that returns all of theFieldcomponents at an arbitrary point within anElement, and agradients()method that returns the gradient components. These non-virtual methods return different types of objects for different types ofFields. -
The virtual
Field::output()methods return genericOutputobjects meant for transferring data and modifying it for output, although they can be useful in other situations. -
Various forms of
Field::operator()return a pointer to the low-levelDegreeOfFreedomobjects that storeFieldvalues in anFEMesh.
See the documentation of each subclass for the details.
Methods
int ndof() const
ndof() returns the number of degrees
of freedom in the Field. This is the
number of data values that must be allocated to store the
Field at each Node of the Mesh.
For CompoundFields,
ndof returns the size of the
in-plane part.
bool is_defined(const CSubProblem* subp) const
is_defined() indicates whether the
Field has been defined on the
given CSubProblem.
Defined Fields have been assigned
values on Nodes.
bool is_active(const CSubProblem *subp) const
is_active() indicates whether the
Field has been activated on
the given CSubProblem.
Active Fields are being solved for.
DegreeOfFreedom* operator()(...) const
DegreeOfFreedom* operator()(constFuncNode*, int component) const; DegreeOfFreedom* operator()(constFuncNode&, int component) const; DegreeOfFreedom* operator()(constElementFuncNodeIterator&, int component) const; DegreeOfFreedom* operator()(constElementFuncNodeIterator&, const IndexP&) const;
This family of methods are all ways of obtaining the value of
a Field at a given FuncNode.
(FuncNode is the subclass of Node for Nodes that
store Field data.) The different
methods are provided for convenience, to allow different
representations of Nodes or
Field components. All of these methods
return a pointer to a DegreeOfFreedom
object, which wraps the actual Field
component value and is stored at the
Node.
DegreeOfFreedoms are low-level, fairly
primitive objects, so these methods cannot be used to extract
aggregate values, such as all of the components of a
multicomponent Field. To do that, or to interpolate a
Field value at an arbitrary point within an Element, see
Field::value()
or Field::output().
double value(...) const
double value(constFEMesh*, constFuncNode*, int component) const; double value(constFEMesh*, constElementFuncNodeIterator&, int component) const; double value(constFEMesh*, constElement*, constMasterPosition&, constFieldIndex& component) const;
The first two forms of value()
evaluate a component of a Field at a Node.
In C++, the given
node must be a FuncNode pointer or a
ElementFuncNodeIterator
reference. In Python, it must be a FuncNode
object.
The third form of value() returns the
value of a component of a Field interpolated at an arbitrary
point within an Element. The point is given in the
Element's master coordinate space. (This version is
currently only available in C++.)
double gradient(...) const
double gradient(constFEMesh*, constElement*, constMasterPosition& position, constFieldIndex& component,SpaceIndexdirection) const;
gradient() returns the gradient in
direction dir of the given
component of the Field at the given
position inside an Element. The position
is given in the Element's master coordinate space.
The direction is 0, 1, or 2, for ,
, and , respectively.
ArithmeticOutputvalue output(...)
ArithmeticOutputValueoutput(constFEMesh*, constElementFuncNodeIterator&) const;ArithmeticOutputValueoutput(constFEMesh*, constFuncNode&) const;
These functions return an OutputValue
object which wraps an OutputVal
object which contains the value of the
Field at the given Node.
These calls are mostly used as a mechanism for generically
transferring Field values to Python
when plotting data, but they can also be useful when writing
Field-dependent Propertys.
The output functions differ from
Field::operator()
and Field::value()
by returning all of the components of a multi-dimensional
Field in one call.
Components* components(Planarity planarity) const;
components() returns a container-like
object that can be iterated over to obtain the indices of a
Field. The optional
Planarity argument determines which
Field components are included. If it
is omitted, ALL_INDICES is
assumed.
For example, in C++ you can write
Field *displacement = Field::getField("Displacement");
for(IndexP index : *displacement->components()) { // ALL_INDICES is implicit
... // Do something with IndexP index
} or, equivalently,
Components* comps = Field::getField("Displacement")->components(ALL_INDICES);
for(ComponentIteratorP i=comps->begin(); i!=comps->end(); i++) {
IndexP index = *i; // Dereference ComponentIterator to get IndexP
... // Do something with IndexP index
} to loop over all components of the displacement field. The equivalent in Python is
for index in displacement.components():
... # Do something with FieldIndex index
Note that the index object returned in C++ is an IndexP,
which is a wrapper around a FieldIndex pointer. In Python
the wrapping is unnecessary and the index object is a
FieldIndex.
See Section 8.4 for an overview, and Components for the details.
Components* outOfPlaneComponents() const;
Like components,
outOfPlaneComponents returns a
container that can be iterated over. However, iterating only
returns the out-of-plane components of the
Field.
![]() |
A Possible Source of Confusion |
|---|---|
|
For example, the out-of-plane part of the
>>> list(Displacement.out_of_plane().components()) [VectorFieldIndex(0), VectorFieldIndex(1), VectorFieldIndex(2)] >>> list(i.integer() for i in Displacement.out_of_plane().components()) [0, 1, 2]
On the other hand,
>>> list(Displacement.out_of_plane().outOfPlaneComponents()) [OutOfPlaneVectorFieldIndex(2)] >>> list(i.integer() for i in Displacement.out_of_plane().outOfPlaneComponents()) [0]
A similar issue arises with |
FieldIndex* getIndex(std::string& name) const;
getIndex() returns a FieldIndex object,
given the name of the desired index.
Different Field subclasses expect
different strings, and return different subclasses of
FieldIndex. For example, a TwoVectorField
expects the name to be
"x" or "y", and
returns a VectorFieldIndex.
In C++ the returned value is a pointer to a newly allocated
object. The caller is responsible for deleting it. An easy
way to do that is to wrap it in an IndexP, which will delete
the pointer in the IndexP's destructor:
Field *field = ...;
IndexP index = IndexP(field->getIndex("x"));


![[Caution]](IMAGES/caution.png)

