Nonlinear Truss Analysis#

This example requires external packages.

pip install contique

This example describes a three-dimensional system of trusses with 5 points and 6 cells (in total 5 active degrees of freedom). Given to its geometry, strong geometric nonlinearities are to be expected when the given reference load is applied. First, we create a mesh, where points are defined by their coordinates and cells by pairs of point connectivities.

import contique
import matplotlib.pyplot as plt
import numpy as np

import felupe as fem

mesh = fem.Mesh(
    points=[
        [2.5, 0, 0],
        [-1.25, 1.25, 0],
        [1, 2, 0],
        [-0.5, 1.5, 1.5],
        [-2.5, 4.5, 2.5],
    ],
    cells=[[0, 3], [1, 3], [2, 3], [2, 4], [1, 4], [3, 4]],
    cell_type="line",
)
region = fem.RegionTruss(mesh)
field = fem.FieldContainer([fem.Field(region, dim=3)])

Beside points and cells we have to define displacement boundary conditions, external forces and the constitutive material formulation for the trusses.

boundaries = fem.BoundaryDict(
    fixed_xyz=fem.Boundary(field[0], mask=[1, 1, 1, 0, 0]),
    fixed_y=fem.Boundary(field[0], mask=[0, 0, 0, 0, 1], skip=(1, 0, 1)),
)
dof0, dof1 = fem.dof.partition(field, boundaries)

solid = fem.TrussBody(
    umat=fem.LinearElastic1D(E=1),
    field=field,
    area=[0.75, 1, 0.5, 0.75, 1, 1],
)

force_3 = np.array([1, 1, -1])
force_4 = np.array([-2, 0, -2])

load_3 = fem.PointLoad(field, [3], force_3)
load_4 = fem.PointLoad(field, [4], force_4)

The undeformed configuration is plotted in a 3d-view.

plotter = mesh.plot(
    line_width=10,
    render_lines_as_tubes=True,
    show_edges=False,
)
plotter.add_points(
    mesh.points,
    color="black",
    point_size=20,
    render_points_as_spheres=True,
)
plotter = boundaries.plot(plotter=plotter)
plotter = load_3.plot(plotter=plotter, color="green", deformed=False)
plotter = load_4.plot(plotter=plotter, color="green", deformed=False)

plotter.show()
ex21 nonlinear truss analysis

For the numeric continuation, the equilibrium function fun and its derivatives w.r.t. the displacement field dfun_du and the load-proportionality-factor dfun_dlpf have to be defined. Here, we’re only interested in the active degrees of freedom.

def fun(x, lpf, *args):
    field[0].values.ravel()[dof1] = x
    load_3.update(force_3 * lpf)
    load_4.update(force_4 * lpf)
    return fem.tools.fun([solid, load_3, load_4], field)[dof1]


def dfun_du(x, lpf, *args):
    field[0].values.ravel()[dof1] = x
    K = fem.tools.jac([solid, load_3, load_4], field)
    return fem.solve.partition(field, K, dof1, dof0)[2]


def dfun_dlpf(x, lpf, *args):
    load_3.update(force_3)
    load_4.update(force_4)
    return fem.tools.fun([load_3, load_4], field)[dof1]

Now that the model is finished, some additional settings have to be chosen. Initial allowed incremental system vector components for both the displacement vector and the load-proportionality-factor (LPF) have to be specified. We use dlpf = 0.005 and du = 0.05 (figured out after some trial and error). Both parameters can’t be specified automatically, as they depend on the model configuration. The job will be limited to a total amount of 163 increments (again, the total number has been figured out after some job runs to get good looking plots).

res = contique.solve(
    fun=fun,
    jac=[dfun_du, dfun_dlpf],
    x0=field[0][dof1],
    lpf0=0,
    dxmax=0.05,
    dlpfmax=0.005,
    maxsteps=163,
    rebalance=True,
    overshoot=1.25,
    tol=1e-8,
    low=1e-2,
    high=4,
    maxiter=8,
)
X = np.array([r.x for r in res])
|Step,C.| Control Component | Norm (Iter.#) | Message     |
|-------|-------------------|---------------|-------------|
|   1,1 |     5+  =>     4- | 8.8e-09 ( 6#) | => re-Cycle |
|     2 |     4-  =>     3- | 1.7e-14 ( 3#) |tol.Overshoot|
|   2,1 |     3-  =>     3- | 1.6e-14 ( 3#) |             |
|   3,1 |     3-  =>     4- | 2.3e-14 ( 3#) |tol.Overshoot|
|   4,1 |     4-  =>     4- | 6.7e-14 ( 3#) |             |
|   5,1 |     4-  =>     4- | 4.2e-13 ( 3#) |             |
|   6,1 |     4-  =>     4- | 2.5e-12 ( 3#) |             |
|   7,1 |     4-  =>     4- | 1.4e-11 ( 3#) |             |
|   8,1 |     4-  =>     4- | 7.1e-11 ( 3#) |             |
|   9,1 |     4-  =>     4- | 5.4e-11 ( 3#) |             |
|  10,1 |     4-  =>     4- | 3.8e-11 ( 3#) |             |
|  11,1 |     4-  =>     4- | 3.0e-11 ( 3#) |             |
|  12,1 |     4-  =>     4- | 2.7e-11 ( 3#) |             |
|  13,1 |     4-  =>     4- | 2.7e-11 ( 3#) |             |
|  14,1 |     4-  =>     4- | 3.1e-11 ( 3#) |             |
|  15,1 |     4-  =>     4- | 4.0e-11 ( 3#) |             |
|  16,1 |     4-  =>     4- | 5.4e-11 ( 3#) |             |
|  17,1 |     4-  =>     4- | 7.6e-11 ( 3#) |             |
|  18,1 |     4-  =>     4- | 1.1e-10 ( 3#) |             |
|  19,1 |     4-  =>     4- | 1.6e-10 ( 3#) |             |
|  20,1 |     4-  =>     4- | 2.3e-10 ( 3#) |             |
|  21,1 |     4-  =>     4- | 3.3e-10 ( 3#) |             |
|  22,1 |     4-  =>     4- | 4.6e-10 ( 3#) |             |
|  23,1 |     4-  =>     4- | 6.1e-10 ( 3#) |             |
|  24,1 |     4-  =>     4- | 6.5e-10 ( 3#) |             |
|  25,1 |     4-  =>     4- | 3.4e-10 ( 3#) |             |
|  26,1 |     4-  =>     4- | 4.1e-10 ( 3#) |             |
|  27,1 |     4-  =>     4- | 1.9e-15 ( 4#) |             |
|  28,1 |     4-  =>     4- | 2.5e-13 ( 4#) |             |
|  29,1 |     4-  =>     2- | 4.7e-11 ( 4#) |tol.Overshoot|
|  30,1 |     2-  =>     2- | 9.4e-13 ( 4#) |             |
|  31,1 |     2-  =>     2- | 1.9e-12 ( 4#) |             |
|  32,1 |     2-  =>     2- | 3.9e-09 ( 4#) |             |
|  33,1 |     2-  =>     2- | 7.3e-03 ( 8#) |Failed       |
|  34,1 |     2-  =>     4+ | 5.4e-02 ( 8#) |Failed       |
|  35,1 |     2-  =>     4+ | 4.0e-11 ( 4#) |tol.Overshoot|
|  36,1 |     4+  =>     4+ | 2.2e-09 ( 3#) |             |
|  37,1 |     4+  =>     4+ | 2.4e-10 ( 3#) |             |
|  38,1 |     4+  =>     4+ | 2.5e-10 ( 3#) |             |
|  39,1 |     4+  =>     4+ | 1.6e-10 ( 3#) |             |
|  40,1 |     4+  =>     4+ | 3.5e-11 ( 3#) |             |
|  41,1 |     4+  =>     4+ | 1.8e-10 ( 3#) |             |
|  42,1 |     4+  =>     4+ | 1.3e-09 ( 3#) |             |
|  43,1 |     4+  =>     4+ | 7.3e-10 ( 3#) |             |
|  44,1 |     4+  =>     4+ | 2.9e-10 ( 3#) |             |
|  45,1 |     4+  =>     4+ | 1.0e-10 ( 3#) |             |
|  46,1 |     4+  =>     4+ | 3.5e-11 ( 3#) |             |
|  47,1 |     4+  =>     4+ | 1.5e-11 ( 3#) |             |
|  48,1 |     4+  =>     4+ | 1.5e-11 ( 3#) |             |
|  49,1 |     4+  =>     4+ | 1.8e-11 ( 3#) |             |
|  50,1 |     4+  =>     4+ | 2.1e-11 ( 3#) |             |
|  51,1 |     4+  =>     4+ | 2.3e-11 ( 3#) |             |
|  52,1 |     4+  =>     4+ | 2.5e-11 ( 3#) |             |
|  53,1 |     4+  =>     4+ | 2.8e-11 ( 3#) |             |
|  54,1 |     4+  =>     4+ | 3.2e-11 ( 3#) |             |
|  55,1 |     4+  =>     4+ | 3.8e-11 ( 3#) |             |
|  56,1 |     4+  =>     4+ | 4.7e-11 ( 3#) |             |
|  57,1 |     4+  =>     4+ | 6.2e-11 ( 3#) |             |
|  58,1 |     4+  =>     4+ | 8.9e-11 ( 3#) |             |
|  59,1 |     4+  =>     4+ | 1.4e-10 ( 3#) |             |
|  60,1 |     4+  =>     4+ | 2.3e-10 ( 3#) |             |
|  61,1 |     4+  =>     4+ | 4.3e-10 ( 3#) |             |
|  62,1 |     4+  =>     4+ | 9.0e-10 ( 3#) |             |
|  63,1 |     4+  =>     4+ | 2.1e-09 ( 3#) |             |
|  64,1 |     4+  =>     4+ | 5.4e-09 ( 3#) |             |
|  65,1 |     4+  =>     3+ | 2.3e-15 ( 4#) |tol.Overshoot|
|  66,1 |     3+  =>     3+ | 1.9e-09 ( 3#) |             |
|  67,1 |     3+  =>     3+ | 1.5e-09 ( 3#) |             |
|  68,1 |     3+  =>     3+ | 3.4e-09 ( 3#) |             |
|  69,1 |     3+  =>     3+ | 2.4e-15 ( 4#) |             |
|  70,1 |     3+  =>     3+ | 6.5e-04 ( 8#) |Failed       |
|  71,1 |     3+  =>     3+ | 1.4e-15 ( 4#) |             |
|  72,1 |     3+  =>     3+ | 7.0e-04 ( 8#) |Failed       |
|  73,1 |     3+  =>     3+ | 3.1e-15 ( 4#) |             |
|  74,1 |     3+  =>     2- | 4.2e-03 ( 8#) |Failed       |
|  75,1 |     3+  =>     2- | 1.5e-14 ( 4#) |tol.Overshoot|
|  76,1 |     2-  =>     2- | 3.6e-11 ( 3#) |             |
|  77,1 |     2-  =>     2- | 1.2e-11 ( 3#) |             |
|  78,1 |     2-  =>     2- | 4.1e-11 ( 3#) |             |
|  79,1 |     2-  =>     2- | 1.4e-10 ( 3#) |             |
|  80,1 |     2-  =>     2- | 5.4e-10 ( 3#) |             |
|  81,1 |     2-  =>     3- | 2.5e-09 ( 3#) |tol.Overshoot|
|  82,1 |     3-  =>     3- | 4.2e-14 ( 4#) |             |
|  83,1 |     3-  =>     3- | 4.3e-15 ( 4#) |             |
|  84,1 |     3-  =>     3- | 7.9e-09 ( 3#) |             |
|  85,1 |     3-  =>     3- | 7.5e-09 ( 3#) |             |
|  86,1 |     3-  =>     3- | 3.7e-10 ( 3#) |             |
|  87,1 |     3-  =>     4- | 1.7e-09 ( 3#) |tol.Overshoot|
|  88,1 |     4-  =>     4- | 3.0e-10 ( 3#) |             |
|  89,1 |     4-  =>     4- | 3.0e-10 ( 3#) |             |
|  90,1 |     4-  =>     4- | 2.5e-10 ( 3#) |             |
|  91,1 |     4-  =>     4- | 1.9e-10 ( 3#) |             |
|  92,1 |     4-  =>     4- | 1.3e-10 ( 3#) |             |
|  93,1 |     4-  =>     4- | 9.3e-11 ( 3#) |             |
|  94,1 |     4-  =>     4- | 6.5e-11 ( 3#) |             |
|  95,1 |     4-  =>     4- | 4.8e-11 ( 3#) |             |
|  96,1 |     4-  =>     4- | 3.9e-11 ( 3#) |             |
|  97,1 |     4-  =>     4- | 3.7e-11 ( 3#) |             |
|  98,1 |     4-  =>     4- | 4.3e-11 ( 3#) |             |
|  99,1 |     4-  =>     4- | 5.9e-11 ( 3#) |             |
| 100,1 |     4-  =>     4- | 9.7e-11 ( 3#) |             |
| 101,1 |     4-  =>     4- | 1.8e-10 ( 3#) |             |
| 102,1 |     4-  =>     4- | 3.9e-10 ( 3#) |             |
| 103,1 |     4-  =>     4- | 9.8e-10 ( 3#) |             |
| 104,1 |     4-  =>     4- | 3.0e-09 ( 3#) |             |
| 105,1 |     4-  =>     4- | 9.0e-16 ( 4#) |             |
| 106,1 |     4-  =>     4- | 2.9e-13 ( 4#) |             |
| 107,1 |     4-  =>     3+ | 2.5e-11 ( 5#) | => re-Cycle |
|     2 |     3+  =>     3+ | 1.5e-10 ( 4#) |             |
| 108,1 |     3+  =>     3+ | 1.9e-10 ( 4#) |             |
| 109,1 |     3+  =>     3+ | 4.3e-12 ( 4#) |             |
| 110,1 |     3+  =>     3+ | 6.1e-15 ( 4#) |             |
| 111,1 |     3+  =>     3+ | 9.7e-09 ( 3#) |             |
| 112,1 |     3+  =>     3+ | 5.6e-09 ( 3#) |             |
| 113,1 |     3+  =>     3+ | 3.2e-09 ( 3#) |             |
| 114,1 |     3+  =>     3+ | 2.0e-09 ( 3#) |             |
| 115,1 |     3+  =>     3+ | 6.7e-09 ( 3#) |             |
| 116,1 |     3+  =>     3+ | 3.8e-15 ( 4#) |             |
| 117,1 |     3+  =>     3+ | 6.1e-15 ( 4#) |             |
| 118,1 |     3+  =>     3+ | 8.0e-09 ( 3#) |             |
| 119,1 |     3+  =>     3+ | 4.2e-10 ( 3#) |             |
| 120,1 |     3+  =>     3+ | 7.0e-10 ( 3#) |             |
| 121,1 |     3+  =>     3+ | 5.9e-10 ( 3#) |             |
| 122,1 |     3+  =>     3+ | 3.0e-10 ( 3#) |             |
| 123,1 |     3+  =>     3+ | 1.3e-10 ( 3#) |             |
| 124,1 |     3+  =>     3+ | 1.1e-10 ( 3#) |             |
| 125,1 |     3+  =>     3+ | 2.6e-10 ( 3#) |             |
| 126,1 |     3+  =>     3+ | 4.5e-10 ( 3#) |             |
| 127,1 |     3+  =>     3+ | 5.5e-10 ( 3#) |             |
| 128,1 |     3+  =>     3+ | 5.1e-10 ( 3#) |             |
| 129,1 |     3+  =>     3+ | 7.0e-10 ( 3#) |             |
| 130,1 |     3+  =>     3+ | 2.3e-09 ( 3#) |             |
| 131,1 |     3+  =>     3+ | 7.3e-09 ( 3#) |             |
| 132,1 |     3+  =>     3+ | 5.0e-15 ( 4#) |             |
| 133,1 |     3+  =>     4- | 3.1e-13 ( 4#) |tol.Overshoot|
| 134,1 |     4-  =>     4- | 3.5e-14 ( 4#) |             |
| 135,1 |     4-  =>     4- | 5.1e-09 ( 3#) |             |
| 136,1 |     4-  =>     4- | 1.9e-09 ( 3#) |             |
| 137,1 |     4-  =>     4- | 1.7e-09 ( 3#) |             |
| 138,1 |     4-  =>     4- | 1.6e-09 ( 3#) |             |
| 139,1 |     4-  =>     4- | 1.2e-09 ( 3#) |             |
| 140,1 |     4-  =>     4- | 8.9e-10 ( 3#) |             |
| 141,1 |     4-  =>     4- | 8.2e-10 ( 3#) |             |
| 142,1 |     4-  =>     4- | 1.0e-09 ( 3#) |             |
| 143,1 |     4-  =>     4- | 1.5e-09 ( 3#) |             |
| 144,1 |     4-  =>     4- | 2.8e-09 ( 3#) |             |
| 145,1 |     4-  =>     4- | 6.1e-09 ( 3#) |             |
| 146,1 |     4-  =>     3- | 6.8e-16 ( 4#) |tol.Overshoot|
| 147,1 |     3-  =>     3- | 2.3e-10 ( 3#) |             |
| 148,1 |     3-  =>     3- | 8.2e-11 ( 3#) |             |
| 149,1 |     3-  =>     3- | 3.9e-11 ( 3#) |             |
| 150,1 |     3-  =>     3- | 2.7e-11 ( 3#) |             |
| 151,1 |     3-  =>     3- | 2.3e-11 ( 3#) |             |
| 152,1 |     3-  =>     3- | 2.1e-11 ( 3#) |             |
| 153,1 |     3-  =>     3- | 2.0e-11 ( 3#) |             |
| 154,1 |     3-  =>     3- | 2.1e-11 ( 3#) |             |
| 155,1 |     3-  =>     3- | 2.3e-11 ( 3#) |             |
| 156,1 |     3-  =>     3- | 2.8e-11 ( 3#) |             |
| 157,1 |     3-  =>     3- | 3.6e-11 ( 3#) |             |
| 158,1 |     3-  =>     3- | 4.8e-11 ( 3#) |             |
| 159,1 |     3-  =>     3- | 6.7e-11 ( 3#) |             |
| 160,1 |     3-  =>     3- | 9.4e-11 ( 3#) |             |
| 161,1 |     3-  =>     3- | 1.4e-10 ( 3#) |             |
| 162,1 |     3-  =>     3- | 1.9e-10 ( 3#) |             |
| 163,1 |     3-  =>     3- | 2.5e-10 ( 3#) |             |

To visualize the deformed state of the model for increment 40 the deformed model plot is generated.

field[0].values.ravel()[dof1] = X[40, :-1]
force = solid.evaluate.gradient(field) * solid.area
plotter = field.view(cell_data={"Force": force}).plot(
    "Force",
    line_width=10,
    show_undeformed=False,
    view="xy",
    cmap="coolwarm",
    clim=[-abs(force).max(), abs(force).max()],
    render_lines_as_tubes=True,
    show_edges=False,
)
plotter.add_points(
    mesh.points + field[0].values,
    color="black",
    point_size=20,
    render_points_as_spheres=True,
)
plotter.show()
ex21 nonlinear truss analysis

Path-tracing of the displacement-LPF curves#

The path-tracing of the deformation process is shown as a History Plot of Displacement-LPF curves for all active DOF. Strong geometrical nonlinearities are observed for all active DOF.

fig, ax = plt.subplots()
ax.plot(*X[:, [0, -1]].T, ".-", label="Point 3")
ax.plot(*X[:, [3, -1]].T, ".-", label="Point 4")
ax.set_xlabel("Displacement X")
ax.set_ylabel("LPF")
ax.legend()
ex21 nonlinear truss analysis
fig, ax = plt.subplots()
ax.plot(*X[:, [1, -1]].T, ".-", label="Point 3")
ax.set_xlabel("Displacement Y")
ax.set_ylabel("LPF")
ax.legend()
ex21 nonlinear truss analysis
fig, ax = plt.subplots()
ax.plot(*X[:, [2, -1]].T, ".-", label="Point 3")
ax.plot(*X[:, [4, -1]].T, ".-", label="Point 4")
ax.set_xlabel("Displacement Z")
ax.set_ylabel("LPF")
ax.legend()
ex21 nonlinear truss analysis

Total running time of the script: (0 minutes 3.543 seconds)

Gallery generated by Sphinx-Gallery