Module DAVE.io.simplify

Simplify

Not every program supports every feature of DAVE. This module contains methods to simplify or re-write a scene such that these features are re-written into something that can be exported.

All methods work in-place. That means that the scene that is passed to the function it modified. As must functions are "destructive" it is recommended to run these on a copy of the original model.

Methods

  • .. method:: split_cables Splits cables into sections without sheaves

  • .. method:: tanks_to_bodies Converts tanks to rigidbodies

See also: DAVE.marine.linearize_buoyancy

Expand source code
"""
Simplify
=========

Not every program supports every feature of DAVE.
This module contains methods to simplify or re-write a scene such that these features are re-written into something
that can be exported.

All methods work in-place. That means that the scene that is passed to the function it modified. As must functions are
"destructive" it is recommended to run these on a copy of the original model.

Methods

- .. method:: split_cables   Splits cables into sections without sheaves

- .. method:: tanks_to_bodies   Converts tanks to rigidbodies

See also:
    DAVE.marine.linearize_buoyancy


"""

"""
  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.

  Ruben de Bruin - 2019

"""

from DAVE import *
import numpy as np
from numpy.linalg import norm

def tanks_to_bodies(s : Scene):
    """Converts tanks with fluid to rigid-bodies. Tanks without fluid are deleted. Rotational inertia of the
    fluid in the tanks (whatever that may be) is fixed to radii of gyration of 0.1m.

    Free-fluid surface is ignored

    Name will be re-used
    """

    tanks = s.nodes_of_type(Tank)

    for t in tanks:
        parent = t.parent
        cog_local = t.cog_local
        mass = t.volume * t.density
        name = t.name

        s.delete(t)

        if mass>1e-6:
            s.new_rigidbody(name, parent=parent, position=cog_local, cog = (0,0,0), mass=mass, inertia_radii=(0.1,0.1,0.1))



def split_cables(s : Scene):
    """Splits cables that run over intermediate points (sheaves) into separate cables. Cables running over
    circles are split into cables connected to the centers of the circles.

    Warning: this function does not compensate for the length of the cable on a circle. Circles are reduced to points.
    """

    cables = s.nodes_of_type(Cable)

    for c in cables:
        if len(c.connections) == 2:
            continue

        # cable with more than 2 connection points
        #
        # Get the points over which the cable runs. For circles get the centerpoint
        points = []
        for p in c.connections:
            if isinstance(p, Point):
                points.append(p)
            elif isinstance(p, Circle):
                points.append(p.parent)

        # calculate the actual length of the cable
        l_segments = []
        for i in range(1,len(points)):
            d = np.array(points[i].global_position) - np.array(points[i-1].global_position)
            l_segments.append(norm(d))

        l_actual = np.sum(l_segments)

        # create new cables
        for i, l_seg in enumerate(l_segments):
            name = s.available_name_like(f'{c.name}_part_{i+1}')
            s.new_cable(name,
                        endA = points[i],
                        endB = points[i+1],
                        EA = c.EA,
                        length = l_seg * c.length / l_actual)  # distribute stretch length evenly

        s.delete(c)

Functions

def split_cables(s: Scene)

Splits cables that run over intermediate points (sheaves) into separate cables. Cables running over circles are split into cables connected to the centers of the circles.

Warning: this function does not compensate for the length of the cable on a circle. Circles are reduced to points.

Expand source code
def split_cables(s : Scene):
    """Splits cables that run over intermediate points (sheaves) into separate cables. Cables running over
    circles are split into cables connected to the centers of the circles.

    Warning: this function does not compensate for the length of the cable on a circle. Circles are reduced to points.
    """

    cables = s.nodes_of_type(Cable)

    for c in cables:
        if len(c.connections) == 2:
            continue

        # cable with more than 2 connection points
        #
        # Get the points over which the cable runs. For circles get the centerpoint
        points = []
        for p in c.connections:
            if isinstance(p, Point):
                points.append(p)
            elif isinstance(p, Circle):
                points.append(p.parent)

        # calculate the actual length of the cable
        l_segments = []
        for i in range(1,len(points)):
            d = np.array(points[i].global_position) - np.array(points[i-1].global_position)
            l_segments.append(norm(d))

        l_actual = np.sum(l_segments)

        # create new cables
        for i, l_seg in enumerate(l_segments):
            name = s.available_name_like(f'{c.name}_part_{i+1}')
            s.new_cable(name,
                        endA = points[i],
                        endB = points[i+1],
                        EA = c.EA,
                        length = l_seg * c.length / l_actual)  # distribute stretch length evenly

        s.delete(c)
def tanks_to_bodies(s: Scene)

Converts tanks with fluid to rigid-bodies. Tanks without fluid are deleted. Rotational inertia of the fluid in the tanks (whatever that may be) is fixed to radii of gyration of 0.1m.

Free-fluid surface is ignored

Name will be re-used

Expand source code
def tanks_to_bodies(s : Scene):
    """Converts tanks with fluid to rigid-bodies. Tanks without fluid are deleted. Rotational inertia of the
    fluid in the tanks (whatever that may be) is fixed to radii of gyration of 0.1m.

    Free-fluid surface is ignored

    Name will be re-used
    """

    tanks = s.nodes_of_type(Tank)

    for t in tanks:
        parent = t.parent
        cog_local = t.cog_local
        mass = t.volume * t.density
        name = t.name

        s.delete(t)

        if mass>1e-6:
            s.new_rigidbody(name, parent=parent, position=cog_local, cog = (0,0,0), mass=mass, inertia_radii=(0.1,0.1,0.1))