General
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
Units
The default unit system is m, kN, mT (metric tonne). G and RHO are defined accordingly.
Rotations
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.
Example
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 settings.py file or by manually overriding them after importing settings.py and before importing scene.py
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() print(s.resources_paths)
All settings are defined in UPPERCASE.
Note :
Changing
G or
RHO
has
no
effect
at
this
moment
as
these
values
would
also
need
to
be
changed
in
the
equilibrium–
core
/ 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:
- Create a scene
- 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() s.new_axis('axis') a = s['axis'] print(a.position)
Nodes
The following node types can be used:
Geometry
The geometry of a scene is setup using
Axis,
Poi and
Sheave nodes.
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.
Forces
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
Connectors connect two or more nodes and can apply a force on them based on their positions and orientations.
Forces
Forces apply a force to a node. The magnitude of the force may depend on the position and/or orientation of the node.
Visuals
(Almost) Everything gets better when visualized :-).
Inertia
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.
Others
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.
Scene
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:
- Get all nodes of a type, use :
Scene.nodes_of_type()
- Get all nodes that depend on a node :
Scene.nodes_depending_on()
- Get all child nodes :
Scene.nodes_with_parent()
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:
Scene.delete(). This deletes a node from the scene. All nodes that depend on this node will be deleted as well.
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
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.
Optimizations
A goal-seek function is available:
Scene.goal_seek().
Resources
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.