Examples of how shearforces and bending moments are calculated#

# Make the figures a bit larger
import matplotlib.pyplot as plt
plt.rcParams.update({"figure.dpi": 100})
from DAVE import *
DAVEcore version = 2.0 from c:\python\miniconda3\envs\book\Lib\site-packages\DAVEcore.cp311-win_amd64.pyd
! Blender not found - Blender can be installed from the microsoft windows store.   if you have blender already and want to be able to use blender then please either:
   - configure windows to open .blend files with blender automatically 
   - add the folder containing blender-launcher.exe to the PATH variable.
s = Scene()

Shear forces and bending moments#

Shear-forces and bending moments can be calculated in any frame and in any direction.

Axis with a load#

The simplest non-trivial example is a cantilever beam with a load at its end.

Since the bar does not need to deflect we can model this as an frame node. The force is added using a point node and a force node. Leaving all the degrees of freedom of the frame node fixed means that the frame is fixed to the world at its origin.

image

s = Scene()
s.new_frame('beam')
s.new_point('point',parent='beam',position=(10,0,0))
s.new_force('load',parent='point',force=(0,0,-20));

Displaying of the shear or moment line can be done in the GUI:

image image

Programmatically a load-shear-moment diagram can be obtained from the frame. A small caveat is that the model needs to be solve before doing this.

s.solve_statics()
lsm = s["beam"].give_load_shear_moment_diagram()

The obtained lsm object contains all the required data for simple and extended plotting:

lsm.plot_simple()
../_images/800277fabdd548c93fca2e7acded16db4558f8e4ea0fd99becaad04c57029701.png ../_images/800277fabdd548c93fca2e7acded16db4558f8e4ea0fd99becaad04c57029701.png

The lsm.plot() method is tailored for writing to full-page PDFs. For that purpose it can be called with a "filename" argument causing it to save to pdf directly.

Off-centerline loads#

Bending is calculated assuming that all forces pass through the X-axis of the analyzed frame (more on that later). Loads that act on a location not on the line are introduced on the nearest point on the line:

image

s = Scene()
s.new_frame('beam')
s.new_point('point',parent='beam',position=(10,0,1))
s.new_force('load',parent='point',force=(22,0,-20))
s.new_point('point2',parent='beam',position=(4,0,-1))
s.new_force('load2',parent='point2',force=(-65,0,0));
s.solve_statics()
lsm = s["beam"].give_load_shear_moment_diagram().plot_simple()
../_images/19ed3d7e2ce4278ff621b3d4bd8ffe43116258d3c29793a15ab9677c3290803f.png

Distributed loads / Footprints#

DAVE typically does not care about how loads are distributed. To be able to have distributed loads in shear and moment diagrams a new concept is introduced: footprints.

A footprint is a shape that defines over which length a loads is introduced on its parent. The length is the projection of the shape in direction of the X-axis of the analysis frame. The footprint is defined by a number of vertices (3d locations). For a point these define the points of the shape relative to the point.

The following example shows a load at x=10 with its footprint defined from -4 to 4.

image

s = Scene()
s.new_frame('beam')
s.new_point('point',parent='beam',position=(10,0,0))
s.new_force('load',parent='point',force=(0,0,-20));
s['point'].footprint = [(-4.0, 0.0, 0.0), (4.0, 0.0, 0.0)]

s.solve_statics()
lsm = s["beam"].give_load_shear_moment_diagram().plot_simple()
../_images/4d4f042904062c7a411739b4f665eeb3ebb10461db5ab69cc8c20e44503542c0.png

A footprint may also be completely outide the point. In that case the resultant of the distributed load on the footprint is calculated to be equal to that of the force:

image

s = Scene()
s.new_frame('beam')
s.new_point('point',parent='beam',position=(3,0,0))
s.new_force('load',parent='point',force=(0,0,-10));
s['point'].footprint = [(0.0, 0.0, 0.0), (4.0, 0.0, 0.0)]

s.solve_statics()
lsm = s["beam"].give_load_shear_moment_diagram()
lsm.plot_simple()
../_images/f2cc37b376caa2e8f7580b20454eda07266282f7c7ce306a0abc3b2b583fdbe0.png ../_images/f2cc37b376caa2e8f7580b20454eda07266282f7c7ce306a0abc3b2b583fdbe0.png

Utilizing the plot() method of shows how the force and footprint are combined into a distributed force:

lsm.plot()
../_images/3068cc30f815432e28673ce286b666483ba1f28ce98e09d95147d815d8bfd3a0.png ../_images/3068cc30f815432e28673ce286b666483ba1f28ce98e09d95147d815d8bfd3a0.png

Directions#

Calculation of the shear and bending moment is not bound to the X-axis of a frame node. In fact any reference frame can be used:

image

Observe that the footprint is projected onto the centerline in a direction perpendicular to the centerline.

Simply provide any other frame to the give_load_shear_moment_diagram method.

s = Scene()
s.new_frame('beam')
s.new_point('point',parent='beam',position=(5,0,3))
s.new_force('load',parent='point',force=(0,0,-10));
s['point'].footprint = [(0.0, 0.0, 0.0), (4.0, 0.0, 0.0)]

# code for some_other_frame
s.new_frame(name='some_other_frame', rotation=(0,-30,0))

s.solve_statics()
lsm = s["beam"].give_load_shear_moment_diagram(s['some_other_frame'])
lsm.plot_simple()
../_images/6be85b6095111ec18bc539f050b2891e21632ff424625504acc3da9dcf7afe87.png ../_images/6be85b6095111ec18bc539f050b2891e21632ff424625504acc3da9dcf7afe87.png

The maximum shear-load in this situation is the component of the force perpendicular to the centerline: cos(30) * 10 =

-10*np.cos(np.radians(30))
-8.660254037844387
x,shear,moment = lsm.give_shear_and_moment()
np.min(shear)
-8.660254037844387

Fluids#

Fluids work similar but with one major difference:

  • Fluids, either as contents of a tank or as buoyancy, result in a distributed load that acts at the location where the vertical force meets the moment/shear axis.

  • A distributed load would act the the neasest points on the moment/shear axis.

The difference is illustrated in the following sketch. On the left a buoyancy shape is attached to the frame, on the right a distriubted force. The shear-force lines are shown in blue.

image

s = Scene()
beam = s.new_frame(name='beam', rotation = (0,30,0))
mesh = s.new_buoyancy(name='Buoyancy mesh',
          parent='beam')
mesh.trimesh.load_file(s.get_resource_path(r'res: cube.obj'), scale = (5.0,2.0,1.0), rotation = (0.0,0.0,0.0), offset = (5,0.0,-1.0))

beam2 = s.new_frame(name='beam2', rotation = (0,30,0), position = (10,0,0))
s.new_point('point',parent='beam2',position=(5,0,-2))
s.new_force('load',parent='point',force=(0,0,20))
s['point'].footprint = [(-2.5, 0.0, 0.0), (2.5, 0.0, 0.0)]

s.solve_statics()

import matplotlib.pyplot as plt
s["beam"].give_load_shear_moment_diagram().plot_simple()
plt.title('Distributed Fluid load')
s["beam2"].give_load_shear_moment_diagram().plot_simple()
plt.title('Distributed load');
../_images/b0c4c697663af2ca13a4431e117623fe1577687a22e0638293bff1945546070a.png ../_images/e13e31788268f06cb2a666083cd809929dd1b96a881cc5a85c8f116a226a04fa.png

Fluid in partially filled tanks#

Behaves just like any other fluid and attaches to the point on the line that is inline with the force.

image

s = Scene()
beam = s.new_frame(name='beam', rotation = (0,20,0))

tank = s.new_tank(name='Tank mesh',
          parent='beam')
tank.trimesh.load_file(s.get_resource_path(r'res: cube.obj'), scale = (5.0,1.0,1.0), rotation = (0.0,0.0,0.0), offset = (-7.5,0.0,1.2))
tank.fill_pct = 30

Self-weight of bodies#

RigidBody elements can have a weight.

By default this is a point-load at the position of the cog.

s = Scene()
body = s.new_rigidbody('body',mass=10, cog = (5,0,0))
s.update()

s['body'].give_load_shear_moment_diagram().plot_simple()
../_images/18ca35a8db589ebf3188e851d7ebb3fb0d40744cc80cae00be940419fee86670.png ../_images/18ca35a8db589ebf3188e851d7ebb3fb0d40744cc80cae00be940419fee86670.png

Footprints are also used to define the distribution of the self-weight to a parent.

In this example the body is located on “frame” at position x=5. The cog of the body is right above its origin. The footprint of the body defines that the force is applied on “frame” from x=-3 to x=3 relative to the origin of the body. That is x=5-3 = 2 to x= 5+3 = 8 on the frame.

s = Scene()
frame = s.new_frame('frame')
body = s.new_rigidbody('body',parent=frame, mass=10, cog = (0,0,1), position = (5,0,0))
body.footprint = [(-3,0,0),(3,0,0)]
s.solve_statics()

s['frame'].give_load_shear_moment_diagram().plot()
../_images/477b7d52e8b105d91e81040068575af90f45c332e958400483a1edae309160de.png ../_images/477b7d52e8b105d91e81040068575af90f45c332e958400483a1edae309160de.png

On the body itself, the footprint is used twice:

  1. For the distribution of the connection force between the body and the frame

  2. For the distribution of the self-weight of the body.

The result is that, in this case, we have two equal and opposite distributed forces acting on “body”, hence both the moment and shear are zero.

s['body'].give_load_shear_moment_diagram().plot()
../_images/33b713fe6b2acf0cdb64f3415ddbef5ee4f4e72b83d7966f5a549927b5ba8c82.png ../_images/33b713fe6b2acf0cdb64f3415ddbef5ee4f4e72b83d7966f5a549927b5ba8c82.png

A “nicer” example would be a rigid-body suspended from two cables:

s = Scene()
b = s.new_rigidbody('body',mass=10, fixed=False, cog = (0,0,0))
b.footprint = [(-3,0,0),(3,0,0)]

s.new_point('p1', parent=b, position = (-5,0,0))
s.new_point('p2', parent=b, position = ( 5,0,0))

s.new_point('s1', position = (-5,0,0))
s.new_point('s2', position = ( 5,0,0))

s.new_cable('c1','p1','s1', length=3, EA=10000)
s.new_cable('c2','p2','s2', length=3, EA=10000)

# from DAVE.jupyter import show
# show(s)
c2 <Cable>
s.solve_statics()
s['body'].give_load_shear_moment_diagram().plot()
../_images/0258b8481a5b734948d7795744d25bc8101ee159d98981042b37bace31216bdd.png ../_images/0258b8481a5b734948d7795744d25bc8101ee159d98981042b37bace31216bdd.png