Axis systems

Axis systems are right-handed.

In the global axis system the Z-axis points up.

The mean sea-surface is defined as Z=0


The default unit system is m, kN, mT (metric tonne). G and RHO are defined accordingly.


Unfortunately there is no standard way of defining rotations in 3D.

DAVE uses a rotation vector to represent rotations. This means that the rotation is defined as a vector with three components (rx,ry,rz). The magnitude of the vector is the rotation in degrees. The axis of rotation is the direction of the vector.

Some examples:

  • (0,0,90) : A rotation of 90 degrees about the Z-axis
  • (0,-10,0) : A rotation of -10 degrees about the Y-axis
  • (10,10,0) : A rotation of sqrt(10^2 + 10^2) about the (1,1,0) axis.

Hint: If euler angles are needed then axis systems can be stacked to obtain the same result.

2D rotations

The following 2D rotations are available: tilt_x, tilt_y, heel, trim, heading and heading_compass. These are derived from the projection of one of the local axis onto the global axis system. For example the tilt about the x-axis is derived from the z-component of the y-axis.


A 3d rotation of (5,0,0) will give a heel of 5 degrees and a tilt_x of 8.7% A 3d rotation of (0,0,120) will give a heading of 120 degrees and a heading_compass of 330.

Filesystem and configuration

By default DAVE will try to create a subfolder “DAVE_models” in the users HOME folder (%homepath% in windows, ~ in linux). This folder will be used for storing temporary files, the log file, and as default save location for assets and models.

DAVE can be configured by changing the settings in the file or by manually overriding them after importing and before importing

import DAVE.settings
from DAVE.scene import *
from pathlib import Path

# override some of the settings
DAVE.settings.RESOURCE_PATH = [Path(r'c:\data')]
DAVE.settings.BLENDER_EXEC = r'C:\Program Files\Blender Foundation\Blender.82 alphalender.exe'

# now create the scene
s = Scene()


All settings are defined in UPPERCASE.Note : ChangingG or RHOhasnoeffectatthismomentasthesevalueswouldalsoneedtobechangedintheequilibriumcore

/ or \

DAVE is multiplatform. It runs fine under windows as well as linux. Windows uses a \ in path definitions while linux uses as /. The python standard pathlib library is used to deal with paths. In most situations however a string will work fine as well.

File format

The standard file-format for saving DAVE scenes and nodes is vanilla python.

When loading a model or asset from a file into a scene the contents of that file are executed in the python interpreter. In the interpreter a variable s is available which refers to the current scene.

This makes it possible to define DAVE models in a very flexible way as arbitrary code can be executed when importing the model. Importing a model into DAVE is basically the same as running a file, so beware of the involed security implications.

Scene and nodes

A node is an item or element in a model. For example a ship or a force. A Scene is a collection of nodes.

The common way of working is as follows:

  1. Create a scene
  2. Add nodes to it

Nodes are added to the scene using .new_nodetype() where nodetype is the type of the node. Each node has a unique name. This is always needs to be provided to the .new_node function. A complete list of node types and corresponding functions is provided later.Example s = Scene() # create an empty scene s.new_poi(‘point 1’) # creates a poi with name anchor s.new_poi(‘point 2’, position = (10,0,0)) # create a second poi at x=10 s.new_cable(‘line’,poiA = ‘point 1’, poiB = ‘point 2′) # creates a cable between the two points s.save_scene(r’test.dave’) # save to file

Nodes in a scene can be referenced by either name or by reference. The .new_nodetype() functions return a reference to the newly created node.

s = Scene()
a = s.new_axis('axis')
    # a is now a reference to node 'axis'

p1 = s.new_poi('poi_1', parent = a )       # refer by reference
p2 = s.new_poi('poi_2', parent = 'axis' )  # refer by name

A reference to a node can also be obtained from the scene using square brackets:

s = Scene()

a = s['axis']


The following node types can be used:


The geometry of a scene is setup using Axis, Poi and Sheave nodes.

TypeProvidesCreate using
AxisAxis system with position and orientationScene.new_axis()
PoiA positionScene.new_poi()
SheaveA disk with a radius and axis directionScene.new_sheave()
RigidBodySame as axis system, but provides a weight as wellScene.new_rigidbody()

A RigidBody is technically idential to an axis system. So everything that applies to Axis also applies to RigidBody and everywhere where an axis system is used a rigidbody can be used as well.

  • Axis can be placed on other axis systems.
  • Pois can be located on an axis system.
  • Sheaves need to be placed on a poi.

If a node has a parent then this means that its position and orientation are expressed relative to that parent. For nodes without a parent everything is defined relative to the global axis system.


Geometry nodes are also used to transfer forces.

Axis and Poi type nodes can receive forces and moments and apply them to their parents. See Poi.applied_force_and_moment_global, Axis.applied_force and Axis.connection_force. Cables running over sheave type nodes will apply the forces directly to the parent node of the sheave.

Degrees of freedom

Axis and RigidBodies can have all their six individual degrees of freedom either fixed or free. If a degree of freedom is free then this means that the node is able to move/rotate in this degree of freedom.


Connectors connect two or more nodes and can apply a force on them based on their positions and orientations.

TypeProvidesCreate using
CableA finite length cable with linear stiffness. A cable runs between two Poi nodes and can run over multiple pois or sheaves. A cable may have a diameter.Scene.new_cable()
LinearBeamA beam connects two axis systems with a linear beam elementScene.new_linear_beam()
LC6dConnects two axis systems with six linear springs. Orientation of the springs is determined by the master axis systemScene.new_linear_connector_6d()
Connector2dConnects two axis systems with two linear springs. Orientation of the springs is determined by shortest distance between the two axis systemsScene.new_connector2d()


Forces apply a force to a node. The magnitude of the force may depend on the position and/or orientation of the node.

TypeProvidesCreate using
ForceAn fixed force and/or moment applied on a PoiScene.new_force()
HydSpringA linear hydrostatic spring attached to an AxisScene.new_hydspring()
BuoyancyA buoyancy mesh attached to an AxisScene.new_buoyancy()


(Almost) Everything gets better when visualized :-).

TypeProvidesCreate using
VisualObj type 3D visuals can be attached to an AxisScene.new_visual()


Inertia is included via PointMass nodes. There is no direct API interface for these elements. They are included under the hood in the Axis nodes (and this in the derived RigidBody node). Also the ballast-system node type employs them to add the inertia of the ballast tanks.


TriMeshSource is a node that defines a triangular mesh. It is not created directly but is created implicitly when creating a buoyuany node. It may be accessed via Buoyancy.trimesh. Multiple buoyancy nodes may share the same TriMeshSource.


Apart from methods to create nodes, Scene also harbors functionality to delete, import, re-order and export nodes.

Creating scenes

A Scene is not a singleton. Multiple scenes can exist next to each-other.

A new and empty Scene can be created as follows:

s = Scene()

where s can be anything, for example my_scene but s is nice and short which is useful as it will be used a lot.

Optionally a filename can be provided to the constructor. In that case that file will be imported.

my_vessel = Scene('path/to/my_vessel.dave_asset')

It is also possible to create a (deep) copy of a scene. This is done as follows:

copy_of_scene = Scene(copy_from = other_scene)

Adding content

Nodes can be added to the scene using the s.new_poi, s.new_axis, etc.. functions which were introduced in the previous section.

Multiple nodes can be imported from file or directly from another Scene object using Scene.load_scene() or Scene.import_scene() respectively.

Note: Beware of name-conflicts when importing. The Scene.import_scene() provides the option to add a prefix to names of imported nodes.

Access nodes

A list of nodes is maintained as the ._nodes property of a scene. It is advised not to use this directly.

Obtaining a reference to a single node can be done using its name:

node = s['node_name']

This is the reason why all node names should be unique. To get a list of all available node names use Scene.print_node_tree()

It is also possible to:

Deleting nodes

Removing nodes can be tricky due to nodes depending on each other. For example deleting a poi which is also used a endpoint for a cable will cause problems for that cable. The same applies to axis systems with nodes on it (children)

Scene.clear() can be used to delete all nodes from a scene.

To delete a single node there are two options:

  1. Scene.delete(). This deletes a node from the scene. All nodes that depend on this node will be deleted as well.
  2. Scene.dissolve(). This “evaporates” the node. Attempts to maintain child nodes. Often used in combination with the containerize option of Scene.import_scene()

Saving or exporting

The standard file-format for saving DAVE scenes and nodes is vanilla python.

The contents of a Scene can be save using Scene.save_scene(). The python code to re-create the scene can be obtained using Scene.give_python_code().


Solving static equilibrium is done using Scene.solve_statics(). If there is a static equilibrium condition then this function will attempt to find it by changing the non-fixed degrees of freedom of the scene.


A goal-seek function is available: Scene.goal_seek().


In the default resource system the resources may be located in any of the folders listed in Scene.resources_paths. The value of this property is initialized with DAVE.settings.RESOURCE_PATH.

Scene.get_resource_list() can be used to obtain a list of all available resources. Scene.get_resource_path() can be used to obtain a full path to a resource with a known name.