FieldML Example: Cube With Pressure Field

This FieldML 0.5 document defines a single element cube model which linearly interpolates a 3-D “coordinates” field and a scalar “pressure” field. A visualisation of the result is shown in the folling figure:

../../_images/fieldml_cube_pressure.png

Visualisation of pressure field over cube, with node numbers.

One thing you will notice about FieldML is that small models such as this cube are quite a bit larger than other formats. However as models get larger the difference is typically only in the size of bulk data, and they may become smaller than competing formats.

All FieldML 0.5 documents begin with a header defining the encoding, with the FieldML tag specifying the version of FieldML including a web link to its schema file and other XML information. This is followed by the single Region element in which all other definitions are made:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Fieldml version="0.5.0" xsi:noNamespaceSchemaLocation="http://www.fieldml.org/resources/xml/0.5/FieldML_0.5.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink">
 <Region name="/">

Next comes an Import block which imports the shapes, basis functions and associated definitions used in this model from the FieldML 0.5 Standard Library:

  <Import xlink:href="http://www.fieldml.org/resources/xml/0.5/FieldML_Library_0.5.xml" region="library">
   <ImportType localName="real.1d" remoteName="real.1d"/>
   <ImportEvaluator localName="shape.unit.cube" remoteName="shape.unit.cube"/>
   <ImportEvaluator localName="interpolator.3d.unit.trilinearLagrange" remoteName="interpolator.3d.unit.trilinearLagrange"/>
   <ImportType localName="parameters.3d.unit.trilinearLagrange" remoteName="parameters.3d.unit.trilinearLagrange"/>
   <ImportEvaluator localName="parameters.3d.unit.trilinearLagrange.argument" remoteName="parameters.3d.unit.trilinearLagrange.argument"/>
   <ImportType localName="parameters.3d.unit.trilinearLagrange.component" remoteName="parameters.3d.unit.trilinearLagrange.component"/>
   <ImportEvaluator localName="parameters.3d.unit.trilinearLagrange.component.argument" remoteName="parameters.3d.unit.trilinearLagrange.component.argument"/>
   <ImportEvaluator localName="chart.3d.argument" remoteName="chart.3d.argument"/>
   <ImportType localName="coordinates.rc.3d" remoteName="coordinates.rc.3d"/>
   <ImportType localName="coordinates.rc.3d.component" remoteName="coordinates.rc.3d.component"/>
   <ImportEvaluator localName="coordinates.rc.3d.component.argument" remoteName="coordinates.rc.3d.component.argument"/>
  </Import>

Note that local names may be different if desired.

OpenCMISS FieldML documents then define the nodes, node derivatives, versions, some predefined constant evaluators for derivatives and versions, and arguments for each Type:

  <EnsembleType name="nodes">
   <Members>
    <MemberRange min="1" max="8"/>
   </Members>
  </EnsembleType>
  <EnsembleType name="node_derivatives">
   <Members>
    <MemberRange min="1" max="8"/>
   </Members>
  </EnsembleType>
  <ConstantEvaluator name="node_derivatives.value" value="1" valueType="node_derivatives"/>
  <ConstantEvaluator name="node_derivatives.d_ds1" value="2" valueType="node_derivatives"/>
  <ConstantEvaluator name="node_derivatives.d_ds2" value="3" valueType="node_derivatives"/>
  <ConstantEvaluator name="node_derivatives.d2_ds1ds2" value="4" valueType="node_derivatives"/>
  <ConstantEvaluator name="node_derivatives.d_ds3" value="5" valueType="node_derivatives"/>
  <ConstantEvaluator name="node_derivatives.d2_ds1ds3" value="6" valueType="node_derivatives"/>
  <ConstantEvaluator name="node_derivatives.d2_ds2ds3" value="7" valueType="node_derivatives"/>
  <ConstantEvaluator name="node_derivatives.d3_ds1ds2ds3" value="8" valueType="node_derivatives"/>
  <EnsembleType name="node_versions">
   <Members>
    <MemberRange min="1" max="1"/>
   </Members>
  </EnsembleType>
  <ConstantEvaluator name="node_versions.1" value="1" valueType="node_versions"/>
  <ArgumentEvaluator name="nodes.argument" valueType="nodes"/>
  <ArgumentEvaluator name="node_derivatives.argument" valueType="node_derivatives"/>
  <ArgumentEvaluator name="node_versions.argument" valueType="node_versions"/>

Next is the argument representing the unknown node parameters, a real value as a function of nodes, node_derivatives and node_versions:

  <ArgumentEvaluator name="nodes.parameters" valueType="real.1d">
   <Arguments>
    <Argument name="nodes.argument"/>
    <Argument name="node_derivatives.argument"/>
    <Argument name="node_versions.argument"/>
   </Arguments>
  </ArgumentEvaluator>

The mesh “mesh3d” is defined, including a constant mapping from the single element label to a cube shape bounds evaluator. Also defined is a mesh argument:

  <MeshType name="mesh3d">
   <Elements name="elements">
    <Members>
     <MemberRange min="1" max="1"/>
    </Members>
   </Elements>
   <Chart name="xi">
    <Components name="mesh3d.xi.components" count="3"/>
   </Chart>
   <Shapes evaluator="shape.unit.cube"/>
  </MeshType>
  <ArgumentEvaluator name="mesh3d.argument" valueType="mesh3d"/>

To allow future support for switching element field template by element, an EnsembleType is created to identify each one. It isn’t used in this model:

  <EnsembleType name="mesh3d.eftIndexes">
   <Members>
    <MemberRange min="1" max="1"/>
   </Members>
  </EnsembleType>

Newer OpenCMISS FieldML 0.5 documents use the following definition of a generic element field template (“eft”) that describes interpolation and parameter mapping from parameters at local nodes, which in more complicated examples may also be scaled by local scale factors. This is fairly verbose, but the final two evaluators should be somewhat self-explanatory; the parameters clearly specifying which node derivative and version is obtained from which local node to become each element parameter:

  <ArgumentEvaluator name="mesh3d.eftIndexes.argument" valueType="mesh3d.eftIndexes"/>
  <EnsembleType name="mesh3d.eft1.nodes">
   <Members>
    <MemberRange min="1" max="8"/>
   </Members>
  </EnsembleType>
  <ArgumentEvaluator name="mesh3d.eft1.nodes.argument" valueType="mesh3d.eft1.nodes"/>
  <ArgumentEvaluator name="mesh3d.eft1.nodeparameters.argument" valueType="real.1d">
   <Arguments>
    <Argument name="node_derivatives.argument"/>
    <Argument name="node_versions.argument"/>
    <Argument name="mesh3d.eft1.nodes.argument"/>
   </Arguments>
  </ArgumentEvaluator>
  <ConstantEvaluator name="mesh3d.eft1.nodes.1" value="1" valueType="mesh3d.eft1.nodes"/>
  <ConstantEvaluator name="mesh3d.eft1.nodes.2" value="2" valueType="mesh3d.eft1.nodes"/>
  <ConstantEvaluator name="mesh3d.eft1.nodes.3" value="3" valueType="mesh3d.eft1.nodes"/>
  <ConstantEvaluator name="mesh3d.eft1.nodes.4" value="4" valueType="mesh3d.eft1.nodes"/>
  <ConstantEvaluator name="mesh3d.eft1.nodes.5" value="5" valueType="mesh3d.eft1.nodes"/>
  <ConstantEvaluator name="mesh3d.eft1.nodes.6" value="6" valueType="mesh3d.eft1.nodes"/>
  <ConstantEvaluator name="mesh3d.eft1.nodes.7" value="7" valueType="mesh3d.eft1.nodes"/>
  <ConstantEvaluator name="mesh3d.eft1.nodes.8" value="8" valueType="mesh3d.eft1.nodes"/>
  <ReferenceEvaluator name="mesh3d.eft1.nodeparameters.node1.value.v1" evaluator="mesh3d.eft1.nodeparameters.argument" valueType="real.1d">
   <Bindings>
    <Bind argument="mesh3d.eft1.nodes.argument" source="mesh3d.eft1.nodes.1"/>
    <Bind argument="node_derivatives.argument" source="node_derivatives.value"/>
    <Bind argument="node_versions.argument" source="node_versions.1"/>
   </Bindings>
  </ReferenceEvaluator>
  <ReferenceEvaluator name="mesh3d.eft1.nodeparameters.node2.value.v1" evaluator="mesh3d.eft1.nodeparameters.argument" valueType="real.1d">
   <Bindings>
    <Bind argument="mesh3d.eft1.nodes.argument" source="mesh3d.eft1.nodes.2"/>
    <Bind argument="node_derivatives.argument" source="node_derivatives.value"/>
    <Bind argument="node_versions.argument" source="node_versions.1"/>
   </Bindings>
  </ReferenceEvaluator>
  <ReferenceEvaluator name="mesh3d.eft1.nodeparameters.node3.value.v1" evaluator="mesh3d.eft1.nodeparameters.argument" valueType="real.1d">
   <Bindings>
    <Bind argument="mesh3d.eft1.nodes.argument" source="mesh3d.eft1.nodes.3"/>
    <Bind argument="node_derivatives.argument" source="node_derivatives.value"/>
    <Bind argument="node_versions.argument" source="node_versions.1"/>
   </Bindings>
  </ReferenceEvaluator>
  <ReferenceEvaluator name="mesh3d.eft1.nodeparameters.node4.value.v1" evaluator="mesh3d.eft1.nodeparameters.argument" valueType="real.1d">
   <Bindings>
    <Bind argument="mesh3d.eft1.nodes.argument" source="mesh3d.eft1.nodes.4"/>
    <Bind argument="node_derivatives.argument" source="node_derivatives.value"/>
    <Bind argument="node_versions.argument" source="node_versions.1"/>
   </Bindings>
  </ReferenceEvaluator>
  <ReferenceEvaluator name="mesh3d.eft1.nodeparameters.node5.value.v1" evaluator="mesh3d.eft1.nodeparameters.argument" valueType="real.1d">
   <Bindings>
    <Bind argument="mesh3d.eft1.nodes.argument" source="mesh3d.eft1.nodes.5"/>
    <Bind argument="node_derivatives.argument" source="node_derivatives.value"/>
    <Bind argument="node_versions.argument" source="node_versions.1"/>
   </Bindings>
  </ReferenceEvaluator>
  <ReferenceEvaluator name="mesh3d.eft1.nodeparameters.node6.value.v1" evaluator="mesh3d.eft1.nodeparameters.argument" valueType="real.1d">
   <Bindings>
    <Bind argument="mesh3d.eft1.nodes.argument" source="mesh3d.eft1.nodes.6"/>
    <Bind argument="node_derivatives.argument" source="node_derivatives.value"/>
    <Bind argument="node_versions.argument" source="node_versions.1"/>
   </Bindings>
  </ReferenceEvaluator>
  <ReferenceEvaluator name="mesh3d.eft1.nodeparameters.node7.value.v1" evaluator="mesh3d.eft1.nodeparameters.argument" valueType="real.1d">
   <Bindings>
    <Bind argument="mesh3d.eft1.nodes.argument" source="mesh3d.eft1.nodes.7"/>
    <Bind argument="node_derivatives.argument" source="node_derivatives.value"/>
    <Bind argument="node_versions.argument" source="node_versions.1"/>
   </Bindings>
  </ReferenceEvaluator>
  <ReferenceEvaluator name="mesh3d.eft1.nodeparameters.node8.value.v1" evaluator="mesh3d.eft1.nodeparameters.argument" valueType="real.1d">
   <Bindings>
    <Bind argument="mesh3d.eft1.nodes.argument" source="mesh3d.eft1.nodes.8"/>
    <Bind argument="node_derivatives.argument" source="node_derivatives.value"/>
    <Bind argument="node_versions.argument" source="node_versions.1"/>
   </Bindings>
  </ReferenceEvaluator>
  <AggregateEvaluator name="mesh3d.eft1.parameters" valueType="parameters.3d.unit.trilinearLagrange">
   <Bindings>
    <BindIndex argument="parameters.3d.unit.trilinearLagrange.component.argument" indexNumber="1"/>
   </Bindings>
   <ComponentEvaluators>
    <ComponentEvaluator component="1" evaluator="mesh3d.eft1.nodeparameters.node1.value.v1"/>
    <ComponentEvaluator component="2" evaluator="mesh3d.eft1.nodeparameters.node2.value.v1"/>
    <ComponentEvaluator component="3" evaluator="mesh3d.eft1.nodeparameters.node3.value.v1"/>
    <ComponentEvaluator component="4" evaluator="mesh3d.eft1.nodeparameters.node4.value.v1"/>
    <ComponentEvaluator component="5" evaluator="mesh3d.eft1.nodeparameters.node5.value.v1"/>
    <ComponentEvaluator component="6" evaluator="mesh3d.eft1.nodeparameters.node6.value.v1"/>
    <ComponentEvaluator component="7" evaluator="mesh3d.eft1.nodeparameters.node7.value.v1"/>
    <ComponentEvaluator component="8" evaluator="mesh3d.eft1.nodeparameters.node8.value.v1"/>
   </ComponentEvaluators>
  </AggregateEvaluator>
  <ReferenceEvaluator name="mesh3d.eft1" evaluator="interpolator.3d.unit.trilinearLagrange" valueType="real.1d">
   <Bindings>
    <Bind argument="parameters.3d.unit.trilinearLagrange.argument" source="mesh3d.eft1.parameters"/>
   </Bindings>
  </ReferenceEvaluator>

The local-to-global node map is serialised here in an inline string DataResource from a ParameterEvaluator:

  <DataResource name="mesh3d.eft1.localtoglobalnodes.data.resource">
   <DataResourceDescription>
    <DataResourceString>1 2 3 4 5 6 7 8 
    </DataResourceString>
   </DataResourceDescription>
   <ArrayDataSource name="mesh3d.eft1.localtoglobalnodes.data.source" location="1" rank="2">
    <RawArraySize>1 8</RawArraySize>
    <ArrayDataSize>1 8</ArrayDataSize>
   </ArrayDataSource>
  </DataResource>
  <ParameterEvaluator name="mesh3d.eft1.localtoglobalnodes" valueType="nodes">
   <DenseArrayData data="mesh3d.eft1.localtoglobalnodes.data.source">
    <DenseIndexes>
     <IndexEvaluator evaluator="mesh3d.argument.elements"/>
     <IndexEvaluator evaluator="mesh3d.eft1.nodes.argument"/>
    </DenseIndexes>
   </DenseArrayData>
  </ParameterEvaluator>

Next the final element field template is made by applying the generic element field template, using bindings to make it in terms of the actual mesh chart, the global node parameters argument and using the known local-to-global node map:

  <ReferenceEvaluator name="mesh3d.eft1.evaluator" evaluator="mesh3d.eft1" valueType="real.1d">
   <Bindings>
    <Bind argument="chart.3d.argument" source="mesh3d.argument.xi"/>
    <Bind argument="mesh3d.eft1.nodeparameters.argument" source="nodes.parameters"/>
    <Bind argument="nodes.argument" source="mesh3d.eft1.localtoglobalnodes"/>
   </Bindings>
  </ReferenceEvaluator>

The field template is now defined. It doesn’t vary with elements, but by convention we still make it a PiecewiseEvaluator over mesh elements:

  <PiecewiseEvaluator name="mesh3d.fieldtemplate1" valueType="real.1d">
   <IndexEvaluators>
    <IndexEvaluator evaluator="mesh3d.argument.elements" indexNumber="1"/>
   </IndexEvaluators>
   <EvaluatorMap default="mesh3d.eft1.evaluator"/>
  </PiecewiseEvaluator>

Next we define the “coordinates” field, including its node parameters. The “coordinates” produces a value of Standard Library Type “coordinates.rc.3d.component.argument” meaning it produces 3-D rectangular Cartesian coordinates:

  <DataResource name="nodes.coordinates.data.resource">
   <DataResourceDescription>
    <DataResourceString>0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 1 1 1 1 
    </DataResourceString>
   </DataResourceDescription>
   <ArrayDataSource name="nodes.coordinates.data.source" location="0" rank="2">
    <RawArraySize>8 3</RawArraySize>
    <ArrayDataSize>8 3</ArrayDataSize>
   </ArrayDataSource>
  </DataResource>
  <ParameterEvaluator name="nodes.coordinates" valueType="real.1d">
   <DenseArrayData data="nodes.coordinates.data.source">
    <DenseIndexes>
     <IndexEvaluator evaluator="nodes.argument"/>
     <IndexEvaluator evaluator="coordinates.rc.3d.component.argument"/>
    </DenseIndexes>
   </DenseArrayData>
  </ParameterEvaluator>
  <AggregateEvaluator name="coordinates" valueType="coordinates.rc.3d">
   <Bindings>
    <BindIndex argument="coordinates.rc.3d.component.argument" indexNumber="1"/>
    <Bind argument="nodes.parameters" source="nodes.coordinates"/>
   </Bindings>
   <ComponentEvaluators default="mesh3d.fieldtemplate1"/>
  </AggregateEvaluator>

Next is the scalar “pressure” field. In this case a new scalar ContinuousType “pressure.domain” defines the codomain of the field:

  <ContinuousType name="pressure.domain"/>
  <DataResource name="nodes.pressure.data.resource">
   <DataResourceDescription>
    <DataResourceString>80000 100000 100000 80000 100000 80000 80000 100000 
    </DataResourceString>
   </DataResourceDescription>
   <ArrayDataSource name="nodes.pressure.data.source" location="0" rank="1">
    <RawArraySize>8</RawArraySize>
    <ArrayDataSize>8</ArrayDataSize>
   </ArrayDataSource>
  </DataResource>
  <ParameterEvaluator name="nodes.pressure" valueType="real.1d">
   <DenseArrayData data="nodes.pressure.data.source">
    <DenseIndexes>
     <IndexEvaluator evaluator="nodes.argument"/>
    </DenseIndexes>
   </DenseArrayData>
  </ParameterEvaluator>
  <ReferenceEvaluator name="pressure" evaluator="mesh3d.fieldtemplate1" valueType="pressure.domain">
   <Bindings>
    <Bind argument="nodes.parameters" source="nodes.pressure"/>
   </Bindings>
  </ReferenceEvaluator>

Finally the document finishes with Region and FieldML end tags:

 </Region>
</Fieldml>