6 Finite Element Models

6.2 FEM model creation

Creating a finite element model in ArtiSynth typically follows the pattern:

   // Create and add main MechModel
   MechModel mech = new MechModel("mech");
   addModel(mech);
   // Create FEM
   FemModel3d fem = new FemModel3d("fem");
   /* ... Setup FEM structure and properties ... */
   // Add FEM to model
   mech.addModel(fem);

The main code block for the FEM setup should do the following:

  • Build the node/element structure

  • Set physical properties

    • density

    • damping

    • material

  • Set boundary conditions

  • Set render properties

Building the FEM structure can be done with the use of factory methods for simple shapes, by loading external files, or by writing code to manually assemble the nodes and elements.

6.2.1 Factory methods

For simple shapes such as beams and ellipsoids, there are factory methods to automatically build the node and element structure. These methods are found in the FemFactory class. Some common methods are

FemFactory.createGrid(...)          // basic beam
FemFactory.createCylinder(...)      // cylinder
FemFactory.createTube(...)          // hollowed cylinder
FemFactory.createEllipsoid(...)     // ellipsoid
FemFactory.createTorus(...)         // torus

The inputs specify the dimensions, resolution, and potentially the type of element to use. The following code creates a basic beam made up of hexahedral elements:

// Create FEM
FemModel3d beam = new FemModel3d("beam");
// Build FEM structure
double[] size = {1.0, 0.25, 0.25};  // widths
int[] res = {8, 2, 2};              // resolution (# elements)
FemFactory.createGrid(beam, FemElementType.Hex,
   size[0], size[1], size[2],
   res[0], res[1], res[2]);
/* ... Set FEM properties ... */
// Add FEM to model
mech.addModel(beam);

6.2.2 Loading external FEM meshes

For more complex geometries, volumetric meshes can be loaded from external files. A list of supported file types is provided in Table 6.3. To load a geometry, an appropriate file reader must be created. Readers capable of reading FEM models implement the interface FemReader, which has the method

readFem( FemModel3d fem )   // populates the FEM based on file contents

Additionally, many FemReader classes have static methods to handle the loading of files for convenience.

Table 6.3: Supported FEM geometry files
Format File extensions Reader Writer
ANSYS .node, .elem AnsysReader AnsysWriter
TetGen .node, .ele TetGenReader TetGenWriter
Abaqus .inp AbaqusReader AbaqusWriter
VTK (ASCII) .vtk VtkAsciiReader

The following code snippet demonstrates how to load a model using the AnsysReader.

// Create FEM
FemModel3d tongue = new FemModel3d("tongue");
// Read FEM from file
try {
   // Get files relative to THIS class
   String nodeFileName = PathFinder.getSourceRelativePath(this,
                            "data/tongue.node");
   String elemFileName = PathFinder.getSourceRelativePath(this,
                            "data/tongue.elem");
   AnsysReader.read(tongue, nodeFileName, elemFileName);
} catch (IOException ioe) {
   // Wrap error, fail to create model
   throw new RuntimeException("Failed to read model", ioe);
}
// Add to model
mech.addModel(tongue);

The method PathFinder.getSourceRelativePath() is used to find a path within the ArtiSynth source tree that is relative to the current model’s source file (Section 2.6). Note the try-catch block. Most of these readers throw an IOException if the read fails.

6.2.3 Generating from surfaces

There are two ways an FEM model can be generated from a surface: by using a FEM mesh generator, and by extruding a surface along its normal direction.

ArtiSynth has the ability to interface directly with the TetGen library (http://tetgen.org) to create a tetrahedral volumetric mesh given a closed and manifold surface. The main Java class for calling TetGen directly is TetgenTessellator. The tessellator has several advanced options, allowing for the computation of convex hulls, and for adding points to a volumetric mesh. For simply creating an FEM from a surface, there is a convenience routine within FemFactory that handles both mesh generation and constructing a FemModel3d:

// Create an FEM from a manifold mesh with a given quality
FemFactory.createFromMesh( PolygonalMesh mesh, double quality );

If quality >0, then points will be added in an attempt to bound the maximum radius-edge ratio (see the -q switch for TetGen). According to the TetGen documentation, the algorithm usually succeeds for a quality ratio of 1.2.

It’s also possible to create thin layer of elements by extruding a surface along its normal direction.

// Create an FEM by extruding a surface
FemFactory.createExtrusion(
      FemModel3d model, int nLayers, double layerThickness, double zOffset,
      PolygonalMesh surface);

For example, to create a two-layer slice of elements centered about a surface of a tendon mesh, one might use

// Load the tendon surface mesh
PolygonalMesh tendonSurface = new PolygonalMesh("tendon.obj");
// Create the tendon
FemModel3d tendon = new FemModel3d("tendon");
int layers = 2;             // 2 layers
double thickness = 0.0005;  // 0.5 mm layer thickness
double offset = thickness;  // center the layers about the surface
// Create the extrusion
FemFactory.createExtrusion( tendon, layers, thickness, offset, tendonSurface );

For this type of extrusion, triangular faces become wedge elements, and quadrilateral faces become hexahedral elements.

Note: for extrusions, no care is taken to ensure element quality; if the surface has a high curvature relative to the total extrusion thickness, then some elements will be inverted.

6.2.4 Building elements in code

A finite element model’s structure can also be manually constructed in code. FemModel3d has the methods:

addNode ( FemNode3d );       // add a node to the model
addElement ( FemElement3d )  // add an element to the model

For an element to successfully be added, all its nodes must already have been added to the model. Nodes can be constructed from a 3D location, and elements from an array of nodes. A convenience routine is available in FemElement3d that automatically creates the appropriate element type given the number of nodes (Table 6.1):

// Creates an element using the supplied nodes
FemElement3d FemElement3d.createElement( FemNode3d[] nodes );

Be aware of node orderings when supplying nodes. For linear elements, ArtiSynth uses a clockwise convention with respect to the outward normal for the first face, followed by the opposite node(s). To determine the correct ordering for a particular element, check the coordinates returned by the function FemElement3dBase.getNodeCoords(). This returns the concatenated coordinate list for an “ideal” element of the given type.

6.2.5 Example: a simple beam model

Figure 6.4: FemBeam model loaded into ArtiSynth.

A complete application model that implements a simple FEM beam is given below.

1 package artisynth.demos.tutorial;
2
3 import java.awt.Color;
4 import java.io.IOException;
5
6 import maspack.render.RenderProps;
7 import artisynth.core.femmodels.FemFactory;
8 import artisynth.core.femmodels.FemModel.SurfaceRender;
9 import artisynth.core.femmodels.FemModel3d;
10 import artisynth.core.femmodels.FemNode3d;
11 import artisynth.core.materials.LinearMaterial;
12 import artisynth.core.mechmodels.MechModel;
13 import artisynth.core.workspace.RootModel;
14
15 public class FemBeam extends RootModel {
16
17    // Models and dimensions
18    FemModel3d fem;
19    MechModel mech;
20    double length = 1;
21    double density = 10;
22    double width = 0.3;
23    double EPS = 1e-15;
24
25    public void build (String[] args) throws IOException {
26
27       // Create and add MechModel
28       mech = new MechModel ("mech");
29       addModel(mech);
30
31       // Create and add FemModel
32       fem = new FemModel3d ("fem");
33       mech.add (fem);
34
35       // Build hex beam using factory method
36       FemFactory.createHexGrid (
37          fem, length, width, width, /*nx=*/6, /*ny=*/3, /*nz=*/3);
38
39       // Set FEM properties
40       fem.setDensity (density);
41       fem.setParticleDamping (0.1);
42       fem.setMaterial (new LinearMaterial (4000, 0.33));
43
44       // Fix left-hand nodes for boundary condition
45       for (FemNode3d n : fem.getNodes()) {
46          if (n.getPosition().x <= -length/2+EPS) {
47             n.setDynamic (false);
48          }
49       }
50
51       // Set rendering properties
52       setRenderProps (fem);
53
54    }
55
56    // sets the FEM’s render properties
57    protected void setRenderProps (FemModel3d fem) {
58       fem.setSurfaceRendering (SurfaceRender.Shaded);
59       RenderProps.setLineColor (fem, Color.BLUE);
60       RenderProps.setFaceColor (fem, new Color (0.5f, 0.5f, 1f));
61    }
62
63 }

This example can be found in artisynth.demos.tutorial.FemBeam. The build() method first creates a MechModel and FemModel3d. A FEM beam is created using a factory method on line 36. This beam is centered at the origin, so its length extends from -length/2 to length/2. The density, damping and material properties are then assigned.

On lines 45–49, a fixed boundary condition is set to the left-hand side of the beam by setting the corresponding nodes to be non-dynamic. Due to numerical precision, a small EPSILON buffer is required to ensure all left-hand boundary nodes are identified (line 46).

Rendering properties are then assigned to the FEM model on line 52. These will be discussed further in Section 6.12.