Follower loading

Follower loading#

Download notebook

Cantilever beam subjected to follower end load.

import veux
import numpy as np
from veux.motion import Motion
import xara
import matplotlib.pyplot as plt

Modeling#

def create_cantilever(ne, element, transform="Corotational02"):
    model = xara.Model(ndm=3, ndf=6)

    L  = 100

    nen = 2
    nmn = ne*(nen-1)+1

    sec = 1
    A = 1.61538e8
    I = 3.5e7
    model.section("ElasticFrame", sec,
                    E=1,
                    G=1,
                    A=A,
                    Ay=A,
                    Az=A,
                    Iy=I*100,
                    Iz=I,
                    J =I
    )

    model.geomTransf(transform, 1, (0,0,1))

    for i,x in enumerate(np.linspace(0, L, nmn)):
        model.node(i, (x,0,0))

    for i in range(ne):
        start = i * (nen - 1)
        nodes = list(range(start, start + nen))
        model.element(element, i+1, nodes,
                      section=sec, transform=1, shear=1)

    model.fix(0,  (1,1,1,  1,1,1))

    return model

Loading#

To create the follower load, use "director" for the basis argument in a xara.FrameLoad.

def apply_loading(model):
    # Tag of the last-created element
    ne = model.getEleTags()[-1]

    pattern = xara.StaticPattern([
        xara.FrameLoad(model,
                    shape="Point",
                    force = [0, 1, 0],
                    basis = "director",
                    offset=[1.0,0,0],
                    elements=[ne]
        )
    ])

    # Add the pattern to the model
    model.pattern(pattern)

Analysis#

def analyze(model: xara.Model, motion):

    speed  =  3000 # animation frames
    Pmax   = 150e3 # N

    model.system('Umfpack')
    model.integrator("LoadControl", Pmax/1000)
    # model.test("NormDispIncr", 1e-10, 500, 1)
    model.test("Energy", 1e-18, 10, 0)
    # model.test("Residual", 1e-6, 200, 2)
    model.algorithm("NewtonLineSearch", 0.8)
    model.analysis("Static")

    u = []
    v = []
    w = []
    P = []
    tip = model.getNodeTags()[-1]
    while model.getTime() < Pmax:
        if model.analyze(1) != 0:
            print(f"Failed at time = {100*model.getTime()/Pmax}% with v = {v[-1]}")
            break
        motion.advance(time=model.getTime()/speed)
        motion.draw_sections(rotation=model.nodeRotation,
                             position=model.nodeDisp)
        u.append(-model.nodeDisp(tip, 1))
        v.append( model.nodeDisp(tip, 2))
        w.append( model.nodeDisp(tip, 3))
        P.append( model.getTime())

    return P, u, v, w
ne = 10

model = create_cantilever(ne, element="ForceFrame")

apply_loading(model)


artist = veux.create_artist(model, model_config=dict(extrude_outline="square"))
artist.draw_nodes(size=10)
artist.draw_sections()
motion = Motion(artist)

P, u, v, w = analyze(model, motion)


motion.add_to(artist.canvas)
artist
fig, ax = plt.subplots()
ax.set_xlabel("Load, $P$")
ax.set_ylabel(r"Displacement")
ax.axvline(0, color='black', linestyle='-', linewidth=1)
ax.axhline(0, color='black', linestyle='-', linewidth=1)
ax.plot(P, u, label="$u$")
ax.plot(P, v, label="$v$")
ax.plot(P, w, label="$w$")
ax.set_xlim([0, None])
ax.legend()
plt.show()
../../_images/5e5ec9b1ff9dba752aaa972c96c0d03bce32b0e70531f2756eeb394cde823b54.png

References#

  1. C. M. Perez and F. C. Filippou, “On nonlinear geometric transformations of finite elements,” Numerical Meth Engineering, vol. 125, no. 17, Sep. 2024, doi: 10.1002/nme.7506.