Rouben Rostamian

MaplePrimes Activity


These are Posts that have been published by Rouben Rostamian

The strandbeest is a walking machine developed by Theo Jansen. Its cleverly designed legs consist of single-degree-of-freedom linkage mechanisms, actuated by the turning of a wind-powered crankshaft.

His working models are generally large - something of the order of the size of a bus. Look for videos on YouTube.  Commercially made small toy models are also available.  This one sells for under $10 and it's fun to assemble and works quite well. Beware that the kit consists of over 100 tiny pieces - so assembling it is not for the impatient type.

Here is a Maple worksheet that produces an animated strandbeest. Link lengths are taken from Theo Jansen's video (go to his site above and click on Explains) where he explains that he calculated the optimal link lengths by applying a genetic algorithm.

Here is a Maple animation of a single leg.  The yellow disk represents the crankshaft.

And here are two legs working in tandem:

Here is the complete beest, running on six legs. The crankshaft turns at a constant angular velocity.

The toy model noted above runs on twelve legs for greater stability.

Download the worksheet: strandbeest.mw

 

Question about deflection and vibration of beams occur with some regularity in this forum.  Search for "beam" to see several pages of hits.

In this post I present a general approach to calculating the vibrational modes of a beam that applies to both single-span and multi-span beams.  The code is not perfectly polished, but it is sufficiently documented to enable the interested user to modify/extend it as needed.

Vibrational modes of multi-span Euler-Bernoulli beams

through Krylov-Dunction functions

Rouben Rostamian
2020-07-19

restart;

Note:  Maple defines the imaginary unit I = sqrt(-1). We want to use the
symbol I as the beam's cross-sectional moment of inertia.
Therefore we redefine the imaginary unit (for which we have no

use) as II and free up the symbol I for our use.

interface(imaginaryunit=II):

with(LinearAlgebra):

 

The Euler-Bernoulli beam equation
"rho*A*((∂)^2u)/((∂)^( )t^2)+E*I*((∂)^(4)u)/((∂)^( )x^(4))=0".

 

We wish to determine the natural modes of vibration of

a possibly multi-span Euler-Bernoulli beam.


Separate the variables by setting u(x, t) = X(x)*T(t).   We get
-
"(rho*A)/(E*I)*(T ' ')/(T)=(X^((4)))/(X)=mu^(4)  "
whence
"T ' ' +(E*I)/(rho*A)*mu^(4)*T =0,           X^((4))-mu^(4)*X=0".

Let omega = sqrt(I*E/(rho*A))*mu^2.  Then

T(t) = C__1*cos(omega*t)+C__2*sin(omega*t)

 and
"X(x)=`c__1`*cosh(mu*x)+`c__2`*sinh(mu*x)+`c__3`*sin(mu*x)+`c__4`*cos(mu*x)."

 

The idea behind the Krylov-Duncan technique is to express X(x) 

in terms an alternative (and equivalent) set of basis
functions K__1 through K__4,, as
X(x) = a__1*K__1(mu*x)+a__2*K__2(mu*x)+a__3*K__3(mu*x)+a__4*K__4(mu*x),

where the functions K__1 through K__4 are defined in the next section.

In some literature the symbols S, T, U, V, are used for these

functions but I find it more sensible to use the indexed function

notation.

The Krylov-Duncan approach is particularly effective in formulating
and finding a multi-span beam's natural modes of vibration.

 

 

The Krylov-Duncan functions

 

The K[i](x) defined by this proc evaluates to the ith

Krylov-Duncan function.

 

Normally the index i will be in the set{1, 2, 3, 4}, however the proc is

set up to accept any integer index (positive or negative).  The proc evaluates

the index modulo 4 to bring the index into the set {1, 2, 3, 4}.   For

instance, K[5](x) and K[-3](x)i are equivalent to K[1](x) .

K := proc(x)
        local n := op(procname);

        if not type(n, integer) then
                return 'procname'(args);
        else
                n := 1 + modp(n-1,4);  # reduce n modulo 4
        end if;

        if n=1 then
                (cosh(x) + cos(x))/2;
        elif n=2 then
                (sinh(x) + sin(x))/2;
        elif n=3 then
                 (cosh(x) - cos(x))/2;
        elif n=4 then
                (sinh(x) - sin(x))/2;
        else
                error "shouldn't be here!";
        end if;

end proc:

Here are the Krylov-Duncan basis functions:

seq(print(cat(`K__`,i)(x) = K[i](x)), i=1..4);

K__1(x) = (1/2)*cosh(x)+(1/2)*cos(x)

K__2(x) = (1/2)*sinh(x)+(1/2)*sin(x)

K__3(x) = (1/2)*cosh(x)-(1/2)*cos(x)

K__4(x) = (1/2)*sinh(x)-(1/2)*sin(x)

and here is what they look like.  All grow exponentially for large x
but are significantly different near the origin.

plot([K[i](x) $i=1..4], x=-Pi..Pi,
        color=["red","Green","blue","cyan"],
        thickness=2,
        legend=['K[1](x)', 'K[2](x)', 'K[3](x)', 'K[4](x)']);

The cyclic property of the derivatives: 
We have diff(K__i(x), x) = `K__i-1`.  Let's verify that:

diff(K[i](x),x) - K[i-1](x) $i=1..4;

0, 0, 0, 0

The fourth derivative of each K__i  function equals itself. This is a consequence of the cyclic property:

diff(K[i](x), x$4) - K[i](x) $ i=1..4;

0, 0, 0, 0

The essential property of the Krylov-Duncan basis function is that their

zeroth through third derivatives at x = 0 form a basis for R^4:

seq((D@@n)(K[1])(0), n=0..3);
seq((D@@n)(K[2])(0), n=0..3);
seq((D@@n)(K[3])(0), n=0..3);
seq((D@@n)(K[4])(0), n=0..3);

1, 0, 0, 0

0, 1, 0, 0

0, 0, 1, 0

0, 0, 0, 1

As noted earlier, in the case of a single-span beam, the modal  shapes

are expressed as
X(x) = a__1*K__1(mu*x)+a__2*K__2(mu*x)+a__3*K__3(mu*x)+a__4*K__4(mu*x).

Then, due to the cyclic property of the derivatives of the Krylov-Duncan

functions, we see that:
"X '(x) = mu*(`a__1`*`K__4`(mu*x)+`a__2`*`K__1`(mu*x)+`a__3`*`K__2`(mu*x)+`a__4`*`K__3`(mu*x))".
X*('`⁢`')(x) = mu^2*(a__1*K__3(mu*x)+a__2*K__4(mu*x)+a__3*K__1(mu*x)+a__4*K__2(mu*x)).
"X ' ' '(x) = mu^(3)*(`a__1`*`K__2`(mu*x)+`a__2`*`K__3`(mu*x)+`a__3`*`K__4`(mu*x)+`a__4`*`K__1`(mu*x))".
Let us note, in particular, that
X(0) = a__1,
"X '(0)=mu*`a__2`",
X*('`⁢`')(0) = mu^2*a__3,
"X ' ' '(0)=mu^(3)*`a__4`".

 

A general approach for solving multi-span beams

 

In a multi-span beam, we write X__i(x) for the deflection of the ith span, where

0 < x and x < L__i and where L__i is the span's length.  The x coordinate indicates the

location within the span, with x = 0 corresponding to the span's left endpoint.

Thus, each span has its own x coordinate system.

 
We assume that the interface of the two adjoining spans is supported on springs

which (a) resist transverse displacement proportional to the displacement (constant of

proportionality of k__d  (d for displacement), and (b) resist rotation proportional to the
slope (constant of proportionality of k__t  (t for torsion or twist). The spans are numbered

from left to right. The interface conditions between spans i and i+1 are

 

1. 

The displacements at the interface match:
X__i(L__i) = `X__i+1`(0).

2. 

The slopes at the interface match
X*`'i`(L__i) = X*`'i+1`(0).

3. 

The difference of the moments just to the left and just to the right of the
support is due to the torque exerted by the torsional spring:
"E*I*(X ' `'i+1`(0)-X ' `'i `(`L__i`))=-`k__t` * X `'i+1`(0),"

4. 

The difference of the shear forces just to the left and just to the right of the
support is due to the force exerted by the linear spring:

"E*I*(X ' ' `'i+1`(0)-X ' ' '(`L__i`))= -`k__d` * `X__i+1`(0).  "

The special case of a pinned support corresponds to k__t = 0 and k__d = infinity.
In that case, condition 3 above implies that X*'`'i+1`(0) = X'*`'i`(L__i),
and condition 4 implies that `X__i+1`(0) = 0.


Let us write the displacements X__i and `X__i+1` in terms of the Krylov-Duncan

functions as:

 

"`X__i`(x)=`a__i,1`*`K__1`(mu*x)+`a__i,2`*`K__2`(mu*x)+`a__i,3`*`K__3`(mu*x)+`a__i,4`*`K__4`(mu*x),  "
"`X__i+1`(x)=`a__i+1,1`*`K__1`(mu*x)+`a__I+1,2`*`K__2`(mu*x)+`a__i+1,3`*`K__3`(mu*x)+`a__i+1,4`*`K__4`(mu*x)."


Then applying the cyclic properties of the Krylov-Duncan functions described

earlier, the four interface conditions translate to the following system of four
equations involving the eight coefficients `a__i,1`, `a__i,2`, () .. (), `a__i+13`, `a__i+1,4`.

"`a__i,1`*`K__1`(mu*`L__i`)+ `a__i,2`*`K__2`(mu*`L__i`)+`a__i,3`*`K__3`(mu*`L__i`)+`a__i,4`*`K__4`(mu*`L__i`)=`a__i+1,1`,"
mu*(`a__i,1`*K__4(mu*L__i)+`a__i,2`*K__1(mu*L__i)+`a__i,3`*K__2(mu*L__i)+`a__i,4`*K__3(mu*L__i)) = mu*`a__i+1,2`,
mu^2*(`a__i,1`*K__3(mu*L__i)+`a__i,2`*K__4(mu*L__i)+`a__i,3`*K__1(mu*L__i)+`a__i,4`*K__2(mu*L__i)-`a__i+1,3`) = -k__t*mu*`a__i+1,2`/(I*E)
mu^3*(`a__i,1`*K__2(mu*L__i)+`a__i,2`*K__3(mu*L__i)+`a__i,3`*K__4(mu*L__i)+`a__i,4`*K__1(mu*L__i)-`a__i+1,4`) = -k__d*`a__i+1,1`/(I*E)

which we write as a matrix equation
(Matrix(4, 8, {(1, 1) = K__1(mu*L__i), (1, 2) = K__2(mu*L__i), (1, 3) = K__3(mu*L__i), (1, 4) = K__4(mu*L__i), (1, 5) = -1, (1, 6) = 0, (1, 7) = 0, (1, 8) = 0, (2, 1) = K__4(mu*L__i), (2, 2) = K__1(mu*L__i), (2, 3) = K__2(mu*L__i), (2, 4) = K__3(mu*L__i), (2, 5) = 0, (2, 6) = -1, (2, 7) = 0, (2, 8) = 0, (3, 1) = K__3(mu*L__i), (3, 2) = K__4(mu*L__i), (3, 3) = K__1(mu*L__i), (3, 4) = K__2(mu*L__i), (3, 5) = 0, (3, 6) = -I*k__t/(mu*E), (3, 7) = -1, (3, 8) = 0, (4, 1) = K__2(mu*L__i), (4, 2) = K__3(mu*L__i), (4, 3) = K__4(mu*L__i), (4, 4) = K__1(mu*L__i), (4, 5) = -I*k__d/(mu^3*E), (4, 6) = 0, (4, 7) = 0, (4, 8) = -1}))*(Vector(8, {(1) = `a__i,1`, (2) = `a__i,2`, (3) = `a__i,3`, (4) = `a__i,4`, (5) = `a__i+1,1`, (6) = `a__i+1,2`, (7) = `a__i+1,3`, (8) = `a__i+1,4`})) = (Vector(8, {(1) = 0, (2) = 0, (3) = 0, (4) = 0, (5) = 0, (6) = 0, (7) = 0, (8) = 0})).

That 4*8 coefficient matrix plays a central role in solving

for modal shapes of multi-span beams.  Let's call it M__interface.

Note that the value of I*E enters that matrix only in combinations with
k__d and k__t.  Therefore we introduce the new symbols

K__d = k__d/(I*E),    K__t = k__t/(I*E).

 

The following proc generates the matrix `#msub(mi("M"),mi("interface"))`.  The parameters K__d and K__t 

are optional and are assigned the default values of infinity and zero, which

corresponds to a pinned support.

 

The % sign in front of each Krylov function makes the function inert, that is, it
prevents it from expanding into trig functions.  This is so that we can

see, visually, what our expressions look like in terms of the K functions.  To

force the evaluation of those inert function, we will apply Maple's value function,

as seen in the subsequent demos.

M_interface := proc(mu, L, {Kd:=infinity, Kt:=0})
        local row1, row2, row3, row4;
        row1 := %K[1](mu*L), %K[2](mu*L), %K[3](mu*L), %K[4](mu*L), -1,  0, 0, 0;
        row2 := %K[4](mu*L), %K[1](mu*L), %K[2](mu*L), %K[3](mu*L),  0, -1, 0, 0;
        row3 := %K[3](mu*L), %K[4](mu*L), %K[1](mu*L), %K[2](mu*L),  0, Kt/mu, -1, 0;
        if Kd = infinity then
                row4 := 0, 0, 0, 0, 1, 0, 0, 0 ;
        else
                row4 := %K[2](mu*L), %K[3](mu*L), %K[4](mu*L), %K[1](mu*L), Kd/mu^3, 0, 0, -1;
        end if:
                return < <row1> | <row2> | <row3> | <row4> >^+;
end proc:

Here is the interface matrix for a pinned support:

M_interface(mu, L);

Matrix(4, 8, {(1, 1) = %K[1](L*mu), (1, 2) = %K[2](L*mu), (1, 3) = %K[3](L*mu), (1, 4) = %K[4](L*mu), (1, 5) = -1, (1, 6) = 0, (1, 7) = 0, (1, 8) = 0, (2, 1) = %K[4](L*mu), (2, 2) = %K[1](L*mu), (2, 3) = %K[2](L*mu), (2, 4) = %K[3](L*mu), (2, 5) = 0, (2, 6) = -1, (2, 7) = 0, (2, 8) = 0, (3, 1) = %K[3](L*mu), (3, 2) = %K[4](L*mu), (3, 3) = %K[1](L*mu), (3, 4) = %K[2](L*mu), (3, 5) = 0, (3, 6) = 0, (3, 7) = -1, (3, 8) = 0, (4, 1) = 0, (4, 2) = 0, (4, 3) = 0, (4, 4) = 0, (4, 5) = 1, (4, 6) = 0, (4, 7) = 0, (4, 8) = 0})

And here is the interface matrix for a general springy support:

M_interface(mu, L, 'Kd'=a, 'Kt'=b);

Matrix(4, 8, {(1, 1) = %K[1](L*mu), (1, 2) = %K[2](L*mu), (1, 3) = %K[3](L*mu), (1, 4) = %K[4](L*mu), (1, 5) = -1, (1, 6) = 0, (1, 7) = 0, (1, 8) = 0, (2, 1) = %K[4](L*mu), (2, 2) = %K[1](L*mu), (2, 3) = %K[2](L*mu), (2, 4) = %K[3](L*mu), (2, 5) = 0, (2, 6) = -1, (2, 7) = 0, (2, 8) = 0, (3, 1) = %K[3](L*mu), (3, 2) = %K[4](L*mu), (3, 3) = %K[1](L*mu), (3, 4) = %K[2](L*mu), (3, 5) = 0, (3, 6) = b/mu, (3, 7) = -1, (3, 8) = 0, (4, 1) = %K[2](L*mu), (4, 2) = %K[3](L*mu), (4, 3) = %K[4](L*mu), (4, 4) = %K[1](L*mu), (4, 5) = a/mu^3, (4, 6) = 0, (4, 7) = 0, (4, 8) = -1})

Note:  In Maple's Java interface, inert quantities are shown in gray.


Note:  The L in this matrix is the length of the span to the left of the interface.
Recall that it is L__i , not `L__i+1`, in the derivation that leads to that matrix.

In a beam consisting of N spans, we write the ith span's deflection X__i(x) as
"`X__i`(x)=`a__i 1`*`K__1`(mu*x)+`a__i 2`*`K__2`(mu*x)+`a__i 3`*`K__3`(mu*x)+`a__i 4`*`K__4`(mu*x)."

Solving the beam amounts to determining the 4*N unknowns `a__i j`, i = 1 .. N, j = 1 .. 4.

which we order as

 

`a__1,1`, `a__1,2`, `a__1,3`, `a__1,4`, `a__2,1`, `a__2,2`, () .. (), `a__N,1`, `a__N,2`, `a__N,3`, `a__N,4`

At each of the N-1 interface supports we have a set of four equations as derived
above, for a total of 4*(N-1) equations.  Additionally, we have four user-supplied

boundary conditions -- two at the extreme left and two at the extreme right of the

overall beam.  Thus, altogether we have 4*N equations which then we solve for the
4*N
 unknown coefficients a__ij.   

The user-supplied boundary conditions at the left end are two equations, each in the
form of a linear combination of the coefficients a__11, a__12, a__13, a__14.  We write M__left for the
2*4 coefficient matrix of that set of equations.  Similarly, the user-supplied boundary
conditions at the right end are two equations, each in the form of a linear combination
of the coefficients a__N1, a__N2, a__N3, a__N4.  We write M__right for the 2*4 coefficient matrix of
that set of equations.   Putting these equations together with those obtained at the interfaces,

we get a linear set of equations represented by a (4*N*4)*N matrix Mwhich can be assembled

easily from the matrices M__left, M__right, and M__interface.  In the case of a 4-span beam the

assembled 16*16matrix Mlooks like this:

The pattern generalizes to any number of spans in the obvious way.

For future use, here we record a few frequently occurring M__left and M__right matrices.

M_left_pinned := <
        1, 0, 0, 0;
        0, 0, 1, 0 >;

Matrix(2, 4, {(1, 1) = 1, (1, 2) = 0, (1, 3) = 0, (1, 4) = 0, (2, 1) = 0, (2, 2) = 0, (2, 3) = 1, (2, 4) = 0})

M_right_pinned := (mu,L) -> <
        %K[1](mu*L), %K[2](mu*L), %K[3](mu*L), %K[4](mu*L);
        %K[3](mu*L), %K[4](mu*L), %K[1](mu*L), %K[2](mu*L) >;  

proc (mu, L) options operator, arrow; `<,>`(`<|>`(%K[1](L*mu), %K[2](L*mu), %K[3](L*mu), %K[4](L*mu)), `<|>`(%K[3](L*mu), %K[4](L*mu), %K[1](L*mu), %K[2](L*mu))) end proc

M_left_clamped := <
        1, 0, 0, 0;
                0, 1, 0, 0 >;

Matrix(2, 4, {(1, 1) = 1, (1, 2) = 0, (1, 3) = 0, (1, 4) = 0, (2, 1) = 0, (2, 2) = 1, (2, 3) = 0, (2, 4) = 0})

M_right_clamped := (mu,L) -> <
        %K[1](mu*L), %K[2](mu*L), %K[3](mu*L), %K[4](mu*L);
        %K[4](mu*L), %K[1](mu*L), %K[2](mu*L), %K[3](mu*L) >;

proc (mu, L) options operator, arrow; `<,>`(`<|>`(%K[1](L*mu), %K[2](L*mu), %K[3](L*mu), %K[4](L*mu)), `<|>`(%K[4](L*mu), %K[1](L*mu), %K[2](L*mu), %K[3](L*mu))) end proc

M_left_free := <
        0, 0, 1, 0;
                0, 0, 0, 1 >;

Matrix(2, 4, {(1, 1) = 0, (1, 2) = 0, (1, 3) = 1, (1, 4) = 0, (2, 1) = 0, (2, 2) = 0, (2, 3) = 0, (2, 4) = 1})

M_right_free := (mu,L) -> <
        %K[3](mu*L), %K[4](mu*L), %K[1](mu*L), %K[2](mu*L);
        %K[2](mu*L), %K[3](mu*L), %K[4](mu*L), %K[1](mu*L) >;

proc (mu, L) options operator, arrow; `<,>`(`<|>`(%K[3](L*mu), %K[4](L*mu), %K[1](L*mu), %K[2](L*mu)), `<|>`(%K[2](L*mu), %K[3](L*mu), %K[4](L*mu), %K[1](L*mu))) end proc

The following proc builds the overall matrixM in the general case.  It takes
two or three arguments.  The first two arguments are the 2*4 matrices
which are called M__left and M__right in the discussion above.  If the beam
consists of a single span, that's all the information that need be supplied.
There is no need for the third argument.

 

In the case of a multi-span beam, in the third argument we supply the
list of the interface matrices M__interface , as in [M__1, M__2, () .. ()], listed in order
of the supports,  from left to right.   An empty list is also
acceptable and is interpreted as having no internal supports,
i.e., a single-span beam.

build_matrix := proc(left_bc::Matrix(2,4), right_bc::Matrix(2,4), interface_matrices::list)
        local N, n, i, M;

        # n is the number of internal supports
        n := 0;

        # adjust n if a third argument is supplied
        if _npassed = 3 then
                n := nops(interface_matrices);
                if n > 0 then
                        for i from 1 to n do
                                if not type(interface_matrices[i], 'Matrix(4,8)') then
                                        error "expected a 4x8 matrix for element %1 in the list of interface matrices", i;
                                end if;
                        end do;
                end if;
        end if;

        N := n + 1;                     # number of spans

        M := Matrix(4*N);
        M[1..2, 1..4] := left_bc;
        for i from 1 to n do
                M[4*i-1..4*i+2, 4*i-3..4*i+4] := interface_matrices[i];
        end do;
        M[4*N-1..4*N, 4*N-3..4*N] := right_bc;
                
        return M;
end proc:

For instance, for a single-span cantilever beam of length L we get the following M matrix:

build_matrix(M_left_clamped, M_right_free(mu,L));

Matrix(4, 4, {(1, 1) = 1, (1, 2) = 0, (1, 3) = 0, (1, 4) = 0, (2, 1) = 0, (2, 2) = 1, (2, 3) = 0, (2, 4) = 0, (3, 1) = %K[3](L*mu), (3, 2) = %K[4](L*mu), (3, 3) = %K[1](L*mu), (3, 4) = %K[2](L*mu), (4, 1) = %K[2](L*mu), (4, 2) = %K[3](L*mu), (4, 3) = %K[4](L*mu), (4, 4) = %K[1](L*mu)})

For a two-span beam with with span lengths of L__1 and L__2, and all three
supports pinned,  we get the following M matrix:

build_matrix(M_left_pinned, M_right_pinned(mu,L[2]), [M_interface(mu, L[1])]);

Matrix(%id = 18446884696906262398)

The matrix M represents a homogeneous linear system (i.e., the right-hand side vector

is zero.)  To obtain a nonzero solution, we set the determinant of M equal to zero.

That gives us a generally transcendental equation in the single unknown mu.  Normally

the equation has infinitely many solutions.  We call these `&mu;__n `, n = 1, 2, () .. () 

Remark: In the special case of pinned supports at the interfaces, that is, when
Kd = infinity, Kt = 0, the matrix M depends only on the span lengths "`L__1`, `L__2`. ..., `L__N`".
It is independent of the parameters rho, A, E, I that enter the Euler-Bernoulli
equations.  The frequencies `&omega;__n` = sqrt(I*E/(rho*A))*`&mu;__n`^2, however, depend on those parameters.

This proc plots the calculated modal shape corresponding to the eigenvalue mu.
The params argument is a set of equations which define the  numerical values

of all the parameters that enter the problem's description, such as the span

lengths.

 

It is assumed that in a multi-span beam, the span lengths are named "L[1], L[2]," etc.,
and in a single-span beam, the length is named L.

plot_beam := proc(M::Matrix,mu::realcons, params::set)
        local null_space, N, a_vals, i, j, A, B, P;
        eval(M, params);
        eval(%, :-mu=mu);
        value(%);  #print(%);
        null_space := NullSpace(%);  #print(%);
        if nops(null_space) <> 1 then
                error "Calculation failed. Increasing Digits and try again";
        end if;

        N := Dimension(M)[1]/4;  # number of spans
        a_vals := convert([seq(seq(a[i,j], j=1..4), i=1..N)] =~ null_space[1], list);

        if N = 1 then
                eval(add(a[1,j]*K[j](mu*x), j=1..4), a_vals);
                P[1] := plot(%, x=0..eval(L,params));
        else
                A := 0;
                B := 0;
                for i from 1 to N do
                        B := A + eval(L[i], params);
                        eval(add(a[i,j]*K[j](mu*x), j=1..4), a_vals);
                        eval(%, x=x-A):
                        P[i] := plot(%, x=A..B);
                        A := B;
                end do;
                unassign('i');
        end if;
        plots:-display([P[i] $i=1..N]);

end proc:

 

A single-span pinned-pinned beam

 

Here we calculate the natural modes of vibration of a single span

beam, pinned at both ends.  The modes are of the form
"X(x) = `a__11``K__1`(mu*x) + `a__12`*`K__2`(mu*x)+`a__13``K__3`(mu*x) + `a__14`*`K__4`(mu*x)."

The matrix M is:

M := build_matrix(M_left_pinned, M_right_pinned(mu,L));

Matrix(4, 4, {(1, 1) = 1, (1, 2) = 0, (1, 3) = 0, (1, 4) = 0, (2, 1) = 0, (2, 2) = 0, (2, 3) = 1, (2, 4) = 0, (3, 1) = %K[1](L*mu), (3, 2) = %K[2](L*mu), (3, 3) = %K[3](L*mu), (3, 4) = %K[4](L*mu), (4, 1) = %K[3](L*mu), (4, 2) = %K[4](L*mu), (4, 3) = %K[1](L*mu), (4, 4) = %K[2](L*mu)})

The characteristic equation:

Determinant(M);
eq := simplify(value(%)) = 0;

-%K[2](L*mu)^2+%K[4](L*mu)^2

-sinh(L*mu)*sin(L*mu) = 0

solve(eq, mu, allsolutions);

Pi*_Z1/L, I*Pi*_Z2/L

We conclude that the eigenvalues are `&mu;__n` = n*Pi/L, n = 1, 2, 3, () .. ().

 

A non-trivial solution of the system M*A = 0 is in the null-space of M:

eval(value(M), mu=n*Pi/L) assuming n::integer;
N := NullSpace(%);

Matrix(4, 4, {(1, 1) = 1, (1, 2) = 0, (1, 3) = 0, (1, 4) = 0, (2, 1) = 0, (2, 2) = 0, (2, 3) = 1, (2, 4) = 0, (3, 1) = (1/2)*cosh(n*Pi)+(1/2)*(-1)^n, (3, 2) = (1/2)*sinh(n*Pi), (3, 3) = (1/2)*cosh(n*Pi)-(1/2)*(-1)^n, (3, 4) = (1/2)*sinh(n*Pi), (4, 1) = (1/2)*cosh(n*Pi)-(1/2)*(-1)^n, (4, 2) = (1/2)*sinh(n*Pi), (4, 3) = (1/2)*cosh(n*Pi)+(1/2)*(-1)^n, (4, 4) = (1/2)*sinh(n*Pi)})

{Vector[column](%id = 18446884696899531350)}

Here are the weights that go with the Krylov functions:

a_vals := convert([a[1,j] $j=1..4] =~ N[1], set);

{a[1, 1] = 0, a[1, 2] = -1, a[1, 3] = 0, a[1, 4] = 1}

and here is the deflection:

add(a[1,j]*K[j](mu*x), j=1..4);
eval(%, a_vals);       # plug in the a_vals calculated above
eval(%, mu=n*Pi/L);    # assert that n is an integer

a[1, 1]*((1/2)*cosh(mu*x)+(1/2)*cos(mu*x))+a[1, 2]*((1/2)*sinh(mu*x)+(1/2)*sin(mu*x))+a[1, 3]*((1/2)*cosh(mu*x)-(1/2)*cos(mu*x))+a[1, 4]*((1/2)*sinh(mu*x)-(1/2)*sin(mu*x))

-sin(mu*x)

-sin(n*Pi*x/L)

We see that the shape functions are simple sinusoids.

 

 

A single-span free-free beam

 

Here we calculate the natural modes of vibration of a single span

beam, free at both ends.  The modes are of the form
X(x) = a__11*K__1(mu*x)+a__12*K__2(mu*x)+a__13*K__3(mu*x)+a__14*K__4(mu*x).

The reasoning behind the calculations is very similar to that in the

previous section, therefore we don't comment on many details.

M := build_matrix(M_left_free, M_right_free(mu,L));

Matrix(4, 4, {(1, 1) = 0, (1, 2) = 0, (1, 3) = 1, (1, 4) = 0, (2, 1) = 0, (2, 2) = 0, (2, 3) = 0, (2, 4) = 1, (3, 1) = %K[3](L*mu), (3, 2) = %K[4](L*mu), (3, 3) = %K[1](L*mu), (3, 4) = %K[2](L*mu), (4, 1) = %K[2](L*mu), (4, 2) = %K[3](L*mu), (4, 3) = %K[4](L*mu), (4, 4) = %K[1](L*mu)})

The characteristic equation:

Determinant(M);
simplify(value(%)) = 0;
eq_tmp := isolate(%, cos(L*mu));

%K[3](L*mu)^2-%K[2](L*mu)*%K[4](L*mu)

1/2-(1/2)*cosh(L*mu)*cos(L*mu) = 0

cos(L*mu) = 1/cosh(L*mu)

Let lambda = L*mu.  Then the characteristic equation takes the form

eq := algsubs(L*mu=lambda, eq_tmp);

cos(lambda) = 1/cosh(lambda)

Here are the graphs of the two sides of the characteristic equation:

plot([lhs,rhs](eq), lambda=0..4*Pi, color=["red","Green"]);

The first three roots are:

lambda__1, lambda__2, lambda__3 :=
        fsolve(eq, lambda=Pi/2..4*Pi, maxsols=3);

4.730040744, 7.853204624, 10.99560783

params := { L=1 };

{L = 1}

mu__1, mu__2, mu__3 := (lambda__1, lambda__2, lambda__3) /~ eval(L, params);

4.730040744, 7.853204624, 10.99560783

plots:-display([
        plot_beam(M, mu__1, params),
        plot_beam(M, mu__2, params),
        plot_beam(M, mu__3, params)],
        color=["red","Green","blue"],
        legend=[mode1, mode2, mode3]);

 

 

A single-span clamped-free cantilever

 

We have a cantilever beam of length L.  It is clamped at the

left end, and free at the right end.

M := build_matrix(M_left_clamped, M_right_free(mu,L));

Matrix(4, 4, {(1, 1) = 1, (1, 2) = 0, (1, 3) = 0, (1, 4) = 0, (2, 1) = 0, (2, 2) = 1, (2, 3) = 0, (2, 4) = 0, (3, 1) = %K[3](L*mu), (3, 2) = %K[4](L*mu), (3, 3) = %K[1](L*mu), (3, 4) = %K[2](L*mu), (4, 1) = %K[2](L*mu), (4, 2) = %K[3](L*mu), (4, 3) = %K[4](L*mu), (4, 4) = %K[1](L*mu)})

Determinant(M);
simplify(value(%)) = 0;
eq_tmp := isolate(%, cos(L*mu));

%K[1](L*mu)^2-%K[2](L*mu)*%K[4](L*mu)

1/2+(1/2)*cosh(L*mu)*cos(L*mu) = 0

cos(L*mu) = -1/cosh(L*mu)

Let lambda = L*mu.  Then the characteristic equation takes the form

eq := algsubs(L*mu=lambda, eq_tmp);

cos(lambda) = -1/cosh(lambda)

Here are the graphs of the two sides of the characteristic equation:

plot([lhs,rhs](eq), lambda=0..3*Pi, color=["red","Green"]);

lambda__1, lambda__2, lambda__3 :=
        fsolve(eq, lambda=Pi/2..3*Pi, maxsols=3);

1.875104068, 4.694091132, 7.854757438

params := { L=1 };

{L = 1}

mu__1, mu__2, mu__3 := (lambda__1, lambda__2, lambda__3) /~ eval(L, params);

1.875104068, 4.694091132, 7.854757438

plots:-display([
        plot_beam(M, mu__1, params),
        plot_beam(M, mu__2, params),
        plot_beam(M, mu__3, params)],
        color=["red","Green","blue"],
        legend=[mode1, mode2, mode3]);

 

 

A dual-span pinned-pinned-free cantilever beam

 

We have a two-span beam of span lengths L__1 and L__2, with the left end of the
first span pinned, the right end of the second span free, and the interface

between the spans on a pinned support.  .

M := build_matrix(
        M_left_pinned,
        M_right_free(mu,L[2]),
                [ M_interface(mu,L[1])] );

Matrix(8, 8, {(1, 1) = 1, (1, 2) = 0, (1, 3) = 0, (1, 4) = 0, (1, 5) = 0, (1, 6) = 0, (1, 7) = 0, (1, 8) = 0, (2, 1) = 0, (2, 2) = 0, (2, 3) = 1, (2, 4) = 0, (2, 5) = 0, (2, 6) = 0, (2, 7) = 0, (2, 8) = 0, (3, 1) = %K[1](L[1]*mu), (3, 2) = %K[2](L[1]*mu), (3, 3) = %K[3](L[1]*mu), (3, 4) = %K[4](L[1]*mu), (3, 5) = -1, (3, 6) = 0, (3, 7) = 0, (3, 8) = 0, (4, 1) = %K[4](L[1]*mu), (4, 2) = %K[1](L[1]*mu), (4, 3) = %K[2](L[1]*mu), (4, 4) = %K[3](L[1]*mu), (4, 5) = 0, (4, 6) = -1, (4, 7) = 0, (4, 8) = 0, (5, 1) = %K[3](L[1]*mu), (5, 2) = %K[4](L[1]*mu), (5, 3) = %K[1](L[1]*mu), (5, 4) = %K[2](L[1]*mu), (5, 5) = 0, (5, 6) = 0, (5, 7) = -1, (5, 8) = 0, (6, 1) = 0, (6, 2) = 0, (6, 3) = 0, (6, 4) = 0, (6, 5) = 1, (6, 6) = 0, (6, 7) = 0, (6, 8) = 0, (7, 1) = 0, (7, 2) = 0, (7, 3) = 0, (7, 4) = 0, (7, 5) = %K[3](L[2]*mu), (7, 6) = %K[4](L[2]*mu), (7, 7) = %K[1](L[2]*mu), (7, 8) = %K[2](L[2]*mu), (8, 1) = 0, (8, 2) = 0, (8, 3) = 0, (8, 4) = 0, (8, 5) = %K[2](L[2]*mu), (8, 6) = %K[3](L[2]*mu), (8, 7) = %K[4](L[2]*mu), (8, 8) = %K[1](L[2]*mu)})

The characteristic equation:

Determinant(M);
eq_tmp1 := simplify(value(%)) = 0;

%K[4](L[1]*mu)^2*%K[4](L[2]*mu)*%K[2](L[2]*mu)-%K[4](L[1]*mu)^2*%K[1](L[2]*mu)^2-%K[4](L[1]*mu)*%K[1](L[1]*mu)*%K[4](L[2]*mu)*%K[1](L[2]*mu)+%K[4](L[1]*mu)*%K[1](L[1]*mu)*%K[3](L[2]*mu)*%K[2](L[2]*mu)+%K[4](L[2]*mu)*%K[1](L[2]*mu)*%K[3](L[1]*mu)*%K[2](L[1]*mu)-%K[4](L[2]*mu)*%K[2](L[2]*mu)*%K[2](L[1]*mu)^2+%K[1](L[2]*mu)^2*%K[2](L[1]*mu)^2-%K[3](L[2]*mu)*%K[2](L[2]*mu)*%K[3](L[1]*mu)*%K[2](L[1]*mu)

(1/4)*(-cos(L[1]*mu)*sinh(L[2]*mu)*cos(L[2]*mu)+cos(L[1]*mu)*sin(L[2]*mu)*cosh(L[2]*mu)+2*sin(L[1]*mu)*cosh(L[2]*mu)*cos(L[2]*mu)+2*sin(L[1]*mu))*sinh(L[1]*mu)+(1/4)*sin(L[1]*mu)*cosh(L[1]*mu)*(sinh(L[2]*mu)*cos(L[2]*mu)-sin(L[2]*mu)*cosh(L[2]*mu)) = 0

That equation does not seem to be amenable to simplification.  The special case of L__1 = L__2, however,

is much nicer:

eval(eq_tmp1, {L[1]=L, L[2]=L}):
eq_tmp2 := simplify(%*4);

(4*cosh(L*mu)*cos(L*mu)+2)*sinh(L*mu)*sin(L*mu)+cos(L*mu)^2-cosh(L*mu)^2 = 0

Let L*mu = lambda:

eq_tmp3 := algsubs(L*mu=lambda, eq_tmp2);

(4*cosh(lambda)*cos(lambda)+2)*sinh(lambda)*sin(lambda)+cos(lambda)^2-cosh(lambda)^2 = 0

That expression grows like cosh(lambda)^2, so we divide through by that to obtain

a better-behaved equation

eq := eq_tmp3/cosh(lambda)^2;

((4*cosh(lambda)*cos(lambda)+2)*sinh(lambda)*sin(lambda)+cos(lambda)^2-cosh(lambda)^2)/cosh(lambda)^2 = 0

plot(lhs(eq), lambda=0..2*Pi);

Here are the first three roots:

lambda__1, lambda__2, lambda__3 :=
         fsolve(eq, lambda=1e-3..2*Pi, maxsols=3);

1.505915458, 3.413100675, 4.437274304

params := { L[1]=1, L[2]=1 };

{L[1] = 1, L[2] = 1}

mu__1, mu__2, mu__3 := (lambda__1, lambda__2, lambda__3) /~ eval(L[1], params);

1.505915458, 3.413100675, 4.437274304

plots:-display([
        plot_beam(M, mu__1, params),
        plot_beam(M, mu__2, params),
        plot_beam(M, mu__3, params)],
        color=["red","Green","blue"],
        legend=[mode1, mode2, mode3]);

 

 

A dual-span clamped-pinned-free cantilever beam

 

We have a two-span beam of span lengths L__1 and L__2, with the left end of the
first span clamped, the right end of the second span free, and the interface

between the spans on a pinned support.  This is different from the previous

case only in the nature of the left boundary condition.

M := build_matrix(
        M_left_clamped,
        M_right_free(mu,L[2]),
        [ M_interface(mu,L[1])] );

Matrix(8, 8, {(1, 1) = 1, (1, 2) = 0, (1, 3) = 0, (1, 4) = 0, (1, 5) = 0, (1, 6) = 0, (1, 7) = 0, (1, 8) = 0, (2, 1) = 0, (2, 2) = 1, (2, 3) = 0, (2, 4) = 0, (2, 5) = 0, (2, 6) = 0, (2, 7) = 0, (2, 8) = 0, (3, 1) = %K[1](L[1]*mu), (3, 2) = %K[2](L[1]*mu), (3, 3) = %K[3](L[1]*mu), (3, 4) = %K[4](L[1]*mu), (3, 5) = -1, (3, 6) = 0, (3, 7) = 0, (3, 8) = 0, (4, 1) = %K[4](L[1]*mu), (4, 2) = %K[1](L[1]*mu), (4, 3) = %K[2](L[1]*mu), (4, 4) = %K[3](L[1]*mu), (4, 5) = 0, (4, 6) = -1, (4, 7) = 0, (4, 8) = 0, (5, 1) = %K[3](L[1]*mu), (5, 2) = %K[4](L[1]*mu), (5, 3) = %K[1](L[1]*mu), (5, 4) = %K[2](L[1]*mu), (5, 5) = 0, (5, 6) = 0, (5, 7) = -1, (5, 8) = 0, (6, 1) = 0, (6, 2) = 0, (6, 3) = 0, (6, 4) = 0, (6, 5) = 1, (6, 6) = 0, (6, 7) = 0, (6, 8) = 0, (7, 1) = 0, (7, 2) = 0, (7, 3) = 0, (7, 4) = 0, (7, 5) = %K[3](L[2]*mu), (7, 6) = %K[4](L[2]*mu), (7, 7) = %K[1](L[2]*mu), (7, 8) = %K[2](L[2]*mu), (8, 1) = 0, (8, 2) = 0, (8, 3) = 0, (8, 4) = 0, (8, 5) = %K[2](L[2]*mu), (8, 6) = %K[3](L[2]*mu), (8, 7) = %K[4](L[2]*mu), (8, 8) = %K[1](L[2]*mu)})

The characteristic equation:

Determinant(M);
eq_tmp1 := simplify(value(%)) = 0;

%K[2](L[1]*mu)*%K[4](L[1]*mu)*%K[4](L[2]*mu)*%K[1](L[2]*mu)-%K[2](L[1]*mu)*%K[4](L[1]*mu)*%K[3](L[2]*mu)*%K[2](L[2]*mu)+%K[2](L[1]*mu)*%K[3](L[1]*mu)*%K[4](L[2]*mu)*%K[2](L[2]*mu)-%K[2](L[1]*mu)*%K[3](L[1]*mu)*%K[1](L[2]*mu)^2-%K[1](L[1]*mu)*%K[4](L[1]*mu)*%K[4](L[2]*mu)*%K[2](L[2]*mu)+%K[1](L[1]*mu)*%K[4](L[1]*mu)*%K[1](L[2]*mu)^2-%K[3](L[1]*mu)^2*%K[4](L[2]*mu)*%K[1](L[2]*mu)+%K[3](L[1]*mu)^2*%K[3](L[2]*mu)*%K[2](L[2]*mu)

(1/4)*((-cos(L[1]*mu)*sin(L[2]*mu)-sin(L[1]*mu)*cos(L[2]*mu))*cosh(L[2]*mu)+cos(L[1]*mu)*sinh(L[2]*mu)*cos(L[2]*mu)-sin(L[1]*mu))*cosh(L[1]*mu)+(1/4)*(sinh(L[1]*mu)*cos(L[1]*mu)*cos(L[2]*mu)+sin(L[2]*mu))*cosh(L[2]*mu)+(1/4)*sinh(L[1]*mu)*cos(L[1]*mu)-(1/4)*sinh(L[2]*mu)*cos(L[2]*mu) = 0

That equation does not seem to be amenable to simplification.  The special case of L__1 = L__2, however,

is much nicer:

eval(eq_tmp1, {L[1]=L, L[2]=L}):
eq_tmp2 := simplify(%*4);

-2*cosh(L*mu)*cos(L*mu)*(sin(L*mu)*cosh(L*mu)-sinh(L*mu)*cos(L*mu)) = 0

Let L*mu = lambda:

eq_tmp3 := algsubs(L*mu=lambda, eq_tmp2);

-2*cosh(lambda)*cos(lambda)*(sin(lambda)*cosh(lambda)-sinh(lambda)*cos(lambda)) = 0

That expression grows like cosh(lambda)^2, so we divide through by that to obtain

a better-behaved equation

eq := eq_tmp3/cosh(lambda)^2;

-2*cos(lambda)*(sin(lambda)*cosh(lambda)-sinh(lambda)*cos(lambda))/cosh(lambda) = 0

plot(lhs(eq), lambda=0..2*Pi);

Here are the first three roots:

lambda__1, lambda__2, lambda__3 :=
         fsolve(eq, lambda=1e-3..2*Pi, maxsols=3);

1.570796326, 3.926602312, 4.712388980

params := { L[1]=1, L[2]=1 };

{L[1] = 1, L[2] = 1}

mu__1, mu__2, mu__3 := (lambda__1, lambda__2, lambda__3) /~ eval(L[1], params);

1.570796326, 3.926602312, 4.712388980

plots:-display([
        plot_beam(M, mu__1, params),
        plot_beam(M, mu__2, params),
        plot_beam(M, mu__3, params)],
        color=["red","Green","blue"],
        legend=[mode1, mode2, mode3]);

 

 

A triple-span free-pinned-pinned-free beam

 

We have a triple-span beam with span lengths of L__1, L__2, L__3.  The beam is supported

on two internal pinned supports.  The extreme ends of the beam are free.

The graphs of the first three modes agree with those

in Figure 3.22 on page 70 of the 2007 article of
Henrik Åkesson, Tatiana Smirnova, Thomas Lagö, and Lars Håkansson.

In the caption of Figure 2.12 on page 28 the span lengths are given
as "`L__1`="3.5, "`L__2`="5.0, "`L__3`="21.5.

interface(rtablesize=12):

M := build_matrix(
        M_left_free,
        M_right_free(mu,L[3]),
        [ M_interface(mu,L[1]), M_interface(mu,L[2])] );

Matrix(12, 12, {(1, 1) = 0, (1, 2) = 0, (1, 3) = 1, (1, 4) = 0, (1, 5) = 0, (1, 6) = 0, (1, 7) = 0, (1, 8) = 0, (1, 9) = 0, (1, 10) = 0, (1, 11) = 0, (1, 12) = 0, (2, 1) = 0, (2, 2) = 0, (2, 3) = 0, (2, 4) = 1, (2, 5) = 0, (2, 6) = 0, (2, 7) = 0, (2, 8) = 0, (2, 9) = 0, (2, 10) = 0, (2, 11) = 0, (2, 12) = 0, (3, 1) = %K[1](L[1]*mu), (3, 2) = %K[2](L[1]*mu), (3, 3) = %K[3](L[1]*mu), (3, 4) = %K[4](L[1]*mu), (3, 5) = -1, (3, 6) = 0, (3, 7) = 0, (3, 8) = 0, (3, 9) = 0, (3, 10) = 0, (3, 11) = 0, (3, 12) = 0, (4, 1) = %K[4](L[1]*mu), (4, 2) = %K[1](L[1]*mu), (4, 3) = %K[2](L[1]*mu), (4, 4) = %K[3](L[1]*mu), (4, 5) = 0, (4, 6) = -1, (4, 7) = 0, (4, 8) = 0, (4, 9) = 0, (4, 10) = 0, (4, 11) = 0, (4, 12) = 0, (5, 1) = %K[3](L[1]*mu), (5, 2) = %K[4](L[1]*mu), (5, 3) = %K[1](L[1]*mu), (5, 4) = %K[2](L[1]*mu), (5, 5) = 0, (5, 6) = 0, (5, 7) = -1, (5, 8) = 0, (5, 9) = 0, (5, 10) = 0, (5, 11) = 0, (5, 12) = 0, (6, 1) = 0, (6, 2) = 0, (6, 3) = 0, (6, 4) = 0, (6, 5) = 1, (6, 6) = 0, (6, 7) = 0, (6, 8) = 0, (6, 9) = 0, (6, 10) = 0, (6, 11) = 0, (6, 12) = 0, (7, 1) = 0, (7, 2) = 0, (7, 3) = 0, (7, 4) = 0, (7, 5) = %K[1](L[2]*mu), (7, 6) = %K[2](L[2]*mu), (7, 7) = %K[3](L[2]*mu), (7, 8) = %K[4](L[2]*mu), (7, 9) = -1, (7, 10) = 0, (7, 11) = 0, (7, 12) = 0, (8, 1) = 0, (8, 2) = 0, (8, 3) = 0, (8, 4) = 0, (8, 5) = %K[4](L[2]*mu), (8, 6) = %K[1](L[2]*mu), (8, 7) = %K[2](L[2]*mu), (8, 8) = %K[3](L[2]*mu), (8, 9) = 0, (8, 10) = -1, (8, 11) = 0, (8, 12) = 0, (9, 1) = 0, (9, 2) = 0, (9, 3) = 0, (9, 4) = 0, (9, 5) = %K[3](L[2]*mu), (9, 6) = %K[4](L[2]*mu), (9, 7) = %K[1](L[2]*mu), (9, 8) = %K[2](L[2]*mu), (9, 9) = 0, (9, 10) = 0, (9, 11) = -1, (9, 12) = 0, (10, 1) = 0, (10, 2) = 0, (10, 3) = 0, (10, 4) = 0, (10, 5) = 0, (10, 6) = 0, (10, 7) = 0, (10, 8) = 0, (10, 9) = 1, (10, 10) = 0, (10, 11) = 0, (10, 12) = 0, (11, 1) = 0, (11, 2) = 0, (11, 3) = 0, (11, 4) = 0, (11, 5) = 0, (11, 6) = 0, (11, 7) = 0, (11, 8) = 0, (11, 9) = %K[3](L[3]*mu), (11, 10) = %K[4](L[3]*mu), (11, 11) = %K[1](L[3]*mu), (11, 12) = %K[2](L[3]*mu), (12, 1) = 0, (12, 2) = 0, (12, 3) = 0, (12, 4) = 0, (12, 5) = 0, (12, 6) = 0, (12, 7) = 0, (12, 8) = 0, (12, 9) = %K[2](L[3]*mu), (12, 10) = %K[3](L[3]*mu), (12, 11) = %K[4](L[3]*mu), (12, 12) = %K[1](L[3]*mu)})

params := { L[1]=3.5, L[2]=5.0, L[3]=21.5 };

{L[1] = 3.5, L[2] = 5.0, L[3] = 21.5}

The characteristic equation

simplify(Determinant(M)):
value(%):
eq := simplify(eval(%, params));

(1/8)*(((2*sin(5.*mu)*sinh(5.*mu)*cos(3.5*mu)+sin(3.5*mu)*(cos(5.*mu)*sinh(5.*mu)-sin(5.*mu)*cosh(5.*mu)))*cosh(3.5*mu)-sinh(3.5*mu)*(cos(5.*mu)*sinh(5.*mu)-sin(5.*mu)*cosh(5.*mu))*cos(3.5*mu)+2*sinh(5.*mu)*sin(5.*mu))*cos(21.5*mu)+sin(21.5*mu)*(((cos(5.*mu)*sinh(5.*mu)-sin(5.*mu)*cosh(5.*mu))*cos(3.5*mu)-cos(5.*mu)*cosh(5.*mu)*sin(3.5*mu)+sin(3.5*mu))*cosh(3.5*mu)+sinh(3.5*mu)*(cos(5.*mu)*cosh(5.*mu)-1)*cos(3.5*mu)+cos(5.*mu)*sinh(5.*mu)-sin(5.*mu)*cosh(5.*mu)))*cosh(21.5*mu)-(1/8)*sinh(21.5*mu)*(((cos(5.*mu)*sinh(5.*mu)-sin(5.*mu)*cosh(5.*mu))*cos(3.5*mu)-cos(5.*mu)*cosh(5.*mu)*sin(3.5*mu)+sin(3.5*mu))*cosh(3.5*mu)+sinh(3.5*mu)*(cos(5.*mu)*cosh(5.*mu)-1)*cos(3.5*mu)+cos(5.*mu)*sinh(5.*mu)-sin(5.*mu)*cosh(5.*mu))*cos(21.5*mu)+(1/8)*(2*sin(5.*mu)*sinh(5.*mu)*cos(3.5*mu)+sin(3.5*mu)*(cos(5.*mu)*sinh(5.*mu)-sin(5.*mu)*cosh(5.*mu)))*cosh(3.5*mu)-(1/8)*sinh(3.5*mu)*(cos(5.*mu)*sinh(5.*mu)-sin(5.*mu)*cosh(5.*mu))*cos(3.5*mu)+(1/4)*sinh(5.*mu)*sin(5.*mu)

plot(eq, mu=0..0.4);

That graphs grows much too fast to be useful.  We moderate it by dividing through
the fastest growing cosh term:

plot(eq/cosh(21.5*mu), mu=0..0.4);

Here are the first three roots:

mu__1, mu__2, mu__3 := fsolve(eq, mu=1e-3..0.4, maxsols=3);

0.8148236435e-1, .2065743153, .3465175842

plots:-display([
        plot_beam(M, mu__1, params),
        plot_beam(M, mu__2, params),
        plot_beam(M, mu__3, params)],
        color=["red","Green","blue"],
        legend=[mode1, mode2, mode3]);

 

 

A triple-span free-spring-spring-free beam

 

We have a triple-span beam with span lengths of L__1, L__2, L__3.  The beam is supported

on two internal springy supports.  The extreme ends of the beam are free.
The numerical data is from the worksheet posted on July 29, 2020 at
https://www.mapleprimes.com/questions/230085-Elasticfoundation-Multispan-EulerBernoulli-Beamthreespan#comment271586

The problem is pretty much the same as the one in the previous section, but the

pinned supports have been replaced by spring supports.

This section's calculations require a little more precision than

Maple's default of 10 digits:

Digits := 15;

15

interface(rtablesize=12):

M := build_matrix(M_left_free, M_right_free(mu,L[3]),
                        [ M_interface(mu, L[1], 'Kd'=kd/(E*I), 'Kt'=kt/(E*I)),
                           M_interface(mu, L[2], 'Kd'=kd/(E*I), 'Kt'=kt/(E*I)) ]);

Matrix(12, 12, {(1, 1) = 0, (1, 2) = 0, (1, 3) = 1, (1, 4) = 0, (1, 5) = 0, (1, 6) = 0, (1, 7) = 0, (1, 8) = 0, (1, 9) = 0, (1, 10) = 0, (1, 11) = 0, (1, 12) = 0, (2, 1) = 0, (2, 2) = 0, (2, 3) = 0, (2, 4) = 1, (2, 5) = 0, (2, 6) = 0, (2, 7) = 0, (2, 8) = 0, (2, 9) = 0, (2, 10) = 0, (2, 11) = 0, (2, 12) = 0, (3, 1) = %K[1](L[1]*mu), (3, 2) = %K[2](L[1]*mu), (3, 3) = %K[3](L[1]*mu), (3, 4) = %K[4](L[1]*mu), (3, 5) = -1, (3, 6) = 0, (3, 7) = 0, (3, 8) = 0, (3, 9) = 0, (3, 10) = 0, (3, 11) = 0, (3, 12) = 0, (4, 1) = %K[4](L[1]*mu), (4, 2) = %K[1](L[1]*mu), (4, 3) = %K[2](L[1]*mu), (4, 4) = %K[3](L[1]*mu), (4, 5) = 0, (4, 6) = -1, (4, 7) = 0, (4, 8) = 0, (4, 9) = 0, (4, 10) = 0, (4, 11) = 0, (4, 12) = 0, (5, 1) = %K[3](L[1]*mu), (5, 2) = %K[4](L[1]*mu), (5, 3) = %K[1](L[1]*mu), (5, 4) = %K[2](L[1]*mu), (5, 5) = 0, (5, 6) = -I*kt/(E*mu), (5, 7) = -1, (5, 8) = 0, (5, 9) = 0, (5, 10) = 0, (5, 11) = 0, (5, 12) = 0, (6, 1) = %K[2](L[1]*mu), (6, 2) = %K[3](L[1]*mu), (6, 3) = %K[4](L[1]*mu), (6, 4) = %K[1](L[1]*mu), (6, 5) = -I*kd/(E*mu^3), (6, 6) = 0, (6, 7) = 0, (6, 8) = -1, (6, 9) = 0, (6, 10) = 0, (6, 11) = 0, (6, 12) = 0, (7, 1) = 0, (7, 2) = 0, (7, 3) = 0, (7, 4) = 0, (7, 5) = %K[1](L[2]*mu), (7, 6) = %K[2](L[2]*mu), (7, 7) = %K[3](L[2]*mu), (7, 8) = %K[4](L[2]*mu), (7, 9) = -1, (7, 10) = 0, (7, 11) = 0, (7, 12) = 0, (8, 1) = 0, (8, 2) = 0, (8, 3) = 0, (8, 4) = 0, (8, 5) = %K[4](L[2]*mu), (8, 6) = %K[1](L[2]*mu), (8, 7) = %K[2](L[2]*mu), (8, 8) = %K[3](L[2]*mu), (8, 9) = 0, (8, 10) = -1, (8, 11) = 0, (8, 12) = 0, (9, 1) = 0, (9, 2) = 0, (9, 3) = 0, (9, 4) = 0, (9, 5) = %K[3](L[2]*mu), (9, 6) = %K[4](L[2]*mu), (9, 7) = %K[1](L[2]*mu), (9, 8) = %K[2](L[2]*mu), (9, 9) = 0, (9, 10) = -I*kt/(E*mu), (9, 11) = -1, (9, 12) = 0, (10, 1) = 0, (10, 2) = 0, (10, 3) = 0, (10, 4) = 0, (10, 5) = %K[2](L[2]*mu), (10, 6) = %K[3](L[2]*mu), (10, 7) = %K[4](L[2]*mu), (10, 8) = %K[1](L[2]*mu), (10, 9) = -I*kd/(E*mu^3), (10, 10) = 0, (10, 11) = 0, (10, 12) = -1, (11, 1) = 0, (11, 2) = 0, (11, 3) = 0, (11, 4) = 0, (11, 5) = 0, (11, 6) = 0, (11, 7) = 0, (11, 8) = 0, (11, 9) = %K[3](L[3]*mu), (11, 10) = %K[4](L[3]*mu), (11, 11) = %K[1](L[3]*mu), (11, 12) = %K[2](L[3]*mu), (12, 1) = 0, (12, 2) = 0, (12, 3) = 0, (12, 4) = 0, (12, 5) = 0, (12, 6) = 0, (12, 7) = 0, (12, 8) = 0, (12, 9) = %K[2](L[3]*mu), (12, 10) = %K[3](L[3]*mu), (12, 11) = %K[4](L[3]*mu), (12, 12) = %K[1](L[3]*mu)})

Calculate the determinant of M.  The result is quite large, so we terminate the command
with a colon so that not to have to look at the result.  If we bothered to peek,  however, we
will see that the determinant has a factor of 1/mu^8.  But that quite obvious by looking at the
entries of the matrix shown above. Two of its rows have 1/mu in them and another two have
1/mu^3. When multiplied, they produce the overall factor of 1/mu^8.

DET := Determinant(M):

Here are the parameters that the determinant depends on:

indets(DET, name);   # the parameters that make up M

{E, I, kd, kt, mu, L[1], L[2], L[3]}

So we provide values for those parameters:

params := {
        L[1]=3.5, L[2]=5.0, L[3]=21.5,
    kd=4.881e9, kt=1.422e4,
    E = 2.05e11, I = 1.1385e-7 };

{E = 0.205e12, I = 0.11385e-6, kd = 0.4881e10, kt = 0.1422e5, L[1] = 3.5, L[2] = 5.0, L[3] = 21.5}

Here is the characteristic equation.  We multiply it by mu^8 to remove the singularity at mu = 0.

mu^8 * value(DET):
eq := eval(%, params):

plot(eq, mu=0..0.6);

We can't see anything useful in that graph.  Let's limit the vertical range:

plot(eq, mu=0..0.6, view=-1e8..1e8);

mu__1, mu__2, mu__3 := fsolve(eq, mu=1e-3..0.6, maxsols=3);

0.843267855136311e-1, .211829475814118, .355117213056777

plots:-display([
        plot_beam(M, mu__1, params),
        plot_beam(M, mu__2, params),
        plot_beam(M, mu__3, params)],
        color=["red","Green","blue"],
        legend=[mode1, mode2, mode3]);

Digits := 10;  # restore the default

10

 

 

 

 

 

 

Download krylov-duncan.mw

 

Maple's pdsolve() is quite capable of solving the PDE that describes the motion of a single-span Euler beam.  As far as I have been able to ascertain, there is no obvious way of applying pdsolve() to solve multi-span beams.  The worksheet attached to this post provides tools for solving multi-span Euler beams.  Shown below are a few demos.  The worksheet contains more demos.

 

A module for solving the Euler beam with the method of lines

beamsolve

 

The beamsolve proc solves a (possibly multi-span) Euler beam equation:``

"rho ((&PartialD;)^2u)/((&PartialD;)^( )t^2)+ ((&PartialD;)^2)/((&PartialD;)^( )x^2)(EI ((&PartialD;)^(2)u)/((&PartialD;)^( )x^(2)))=f"

subject to initial and boundary conditions.  The solution u = u(x, t) is the

transverse deflection of the beam at point x at time t, subject to the load
density (i.e., load per unit length) given by f = f(x, t). The coefficient rho 

is the beam's mass density (mass per unit length), E is the Young's modulus of

the beam's material, and I is the beam's cross-sectional moment of inertia

about the neutral axis.  The figure below illustrates a 3-span beam (drawn in green)
supported on four supports, and loaded by a variable density load (drawn in gray)
which may vary in time.  The objective is to determine the deformed shape of the
beam as a function of time.


The number of spans, their lengths, and the nature of the supports may be specified

as arguments to beamsolve.

 

In this worksheet we assume that rho, E, I are constants for simplicity. Since only
the product of the coefficients E and I enters the calculations, we lump the two

together into a single variable which we indicate with the two-letter symbol EI.

Commonly, EI is referred to as the beam's rigidity.

 

The PDE needs to be supplied with boundary conditions, two at each end, each

condition prescribing a value (possibly time-dependent) for one of u, u__x, u__xx, u__xxx 
(that's 36 possible combinations!) where I have used subscripts to indicate

derivatives.  Thus, for a single-span beam of length L, the following is an admissible

set of boundary conditions:
u(0, t) = 0, u__xx(0, t) = 0, u__xx(L, t) = 0, u__xxx(t) = sin*t.   (Oops, coorection, that last
condition was meant to be uxxx(L,t) = sin t.)

Additionally, the PDE needs to be supplied with initial conditions which express

the initial displacement and the initial velocity:
"u(x,0)=phi(x),   `u__t`(x,0)=psi(x)."

 

The PDE is solved through the Method of Lines.  Thus, each span is subdivided into

subintervals and the PDE's spatial derivatives are approximated through finite differences.

The time derivatives, however, are not discretized.  This reduces the PDE into a set of

ODEs which are solved with Maple's dsolve().  

 

Calling sequence:

        beamsolve(L, n, options)

 

Parameters:

        L:  List of span lengths, in order from left to right, as in [L__1, L__2 .. (), `L__&nu;`].

        n The number of subintervals in the shortest span (for the finite difference approximation)

 

Notes:

• 

It is assumed that the spans are laid back-to-back along the x axis, with the left end
of the overall beam at x = 0.

• 

The interior supports, that is, those supports where any two spans meet, are assumed
to be of the so-called simple type.  A simple support is immobile and it doesn't exert
a bending moment on the beam.  Supports at the far left and far right of the beam can
be of general type; see the BC_left and BC_right options below.

• 

If the beam consists of a single span, then the argument L may be entered as a number
rather than as a list. That is, L__1 is equivalent to [L__1].

 

Options:

        All options are of the form option_name=value, and have built-in default values.

        Only options that are other than the defaults need be specified.

 

        rho: the beam's (constant) mass density per unit length (default: rho = 1)

        EI: the beam's (constant) rigidity (default: EI = 1)

        T: solve the PDE over the time interval 0 < t and t < T (default: T = 1)

        F: an expression in x and t that describes the applied force f(x, t)  (default: F = 0)
        IC: the list [u(x, 0), u__t(x, 0)]of the initial displacement and velocity,  as
                expressions in x (default: IC = [0,0])

        BC_left: a list consisting of a pair of boundary conditions at the left end of
                the overall (possibly multi-span beam.  These can be any two of
                u = alpha(t), u_x = beta(t), u_xx = gamma(t), u_xxx = delta(t). The right-hand sides of these equations

                can be any expression in t.  The left-hand sides should be entered literally as indicated.

                If a right-hand side is omitted, it is taken to be zero.   (default: BC_left = [u, u_xx] which

                corresponds to a simple support).

        BC_right: like BC_left, but for the right end of the overall beam (default: BC_right = "[u,u_xx])"

 

The returned module:

        A call to beamsolve returns a module which presents three methods.  The methods are:

 

        plot (t, refine=val, options)

                plots the solution u(x, t) at time t.  If the discretization in the x direction

                is too coarse and the graph looks non-smooth, the refine option

                (default: refine=1) may be specified to smooth out the graph by introducing

                val number of intermediate points within each discretized subinterval.

                All other options are assumed to be plot options and are passed to plots:-display.

 

        plot3d (m=val, options)

                plots the surface u(x, t).  The optional m = val specification requests

                a grid consisting of val subintervals in the time direction (default: "m=25)"

                Note that this grid is for plotting purposes only; the solution is computed

                as a continuous (not discrete) function of time. All other options are assumed

                to be plot3d options and are passed to plots:-display.

 

        animate (frames=val, refine=val, options)

                produces an animation of the beam's motion.  The frames option (default = 50)

                specifies the number of animation frames.  The refine option is passed to plot
                (see the description above. All other options are assumed to be plot options and
                are passed to plots:-display.

Note:

        In specifying the boundary conditions, the following reminder can be helpful.  If the beam

        is considered to be horizontal, then u is the vertical displacement, `u__x ` is the slope,  EI*u__xx

        is the bending moment, and EI*u__xxx is the transverse shear force.

 

A single-span simply-supported beam with initial velocity

 

The function u(x, t) = sin(Pi*x)*sin(Pi^2*t) is an exact solution of a simply supported beam with

"u(x,0)=0,   `u__t`(x,0)=Pi^(2)sin(Pi x)."  The solution is periodic in time with period 2/Pi.

sol := beamsolve(1, 25, 'T'=2/Pi, 'IC'=[0, Pi^2*sin(Pi*x)]):
sol:-animate(size=[600,250]);

The initial condition u(x, 0) = 0, u__t(x, 0) = 1  does not lead to a separable form, and

therefore the motion is more complex.

sol := beamsolve(1, 25, 'T'=2/Pi, 'IC'=[0, 1]):
sol:-animate(frames=200, size=[600,250]);


 

A single-span cantilever beam

 

A cantilever beam with initial condition "u(x,0)=g(x),  `u__t`(x,0)=0," where g(x) is the
first eigenmode of its free vibration (calculated in another spreadsheet).  The motion is
periodic in time, with period "1.787018777."

g := 0.5*cos(1.875104069*x) - 0.5*cosh(1.875104069*x) - 0.3670477570*sin(1.875104069*x) + 0.3670477570*sinh(1.875104069*x):
sol := beamsolve(1, 25, 'T'=1.787018777, 'BC_left'=[u,u_x], 'BC_right'=[u_xx,u_xxx], 'IC'=[g, 0]):
sol:-animate(size=[600,250]);

If the initial condition is not an eigenmode, then the solution is rather chaotic.

sol := beamsolve(1, 25, 'T'=3.57, 'BC_left'=[u,u_x], 'BC_right'=[u_xx,u_xxx], 'IC'=[-x^2, 0]):
sol:-animate(size=[600,250], frames=100);


 

A single-span cantilever beam with a weight hanging from its free end

 

sol := beamsolve(1, 25, 'T'=3.57, 'BC_left'=[u,u_x], 'BC_right'=[u_xx,u_xxx=1]):
sol:-animate(size=[600,250], frames=100);


 

A single-span cantilever beam with oscillating support

 

sol := beamsolve(1, 25, 'T'=Pi, 'BC_left'=[u=0.1*sin(10*t),u_x], 'BC_right'=[u_xx,u_xxx]):
sol:-animate(size=[600,250], frames=100);


 

A dual-span simply-supported beam with moving load

 

Load moves across a dual-span beam.

The beam continues oscillating after the load leaves.

d := 0.4:  T := 4:  nframes := 100:
myload := - max(0, -6*(x - t)*(d + x - t)/d^3):
sol := beamsolve([1,1], 20, 'T'=T, 'F'=myload):
sol:-animate(frames=nframes):
plots:-animate(plot, [2e-3*myload(x,t), x=0..2, thickness=1, filled=[color="Green"]], t=0..T, frames=nframes):
plots:-display([%%,%], size=[600,250]);


 

A triple-span simply-supported beam with moving load

 

Load moves across a triple-span beam.

The beam continues oscillating after the load leaves.

d := 0.4:  T := 6: nframes := 100:
myload := - max(0, -6*(x - t)*(d + x - t)/d^3):
sol := beamsolve([1,1,1], 20, 'T'=T, 'F'=myload):
sol:-plot3d(m=50);
sol:-animate(frames=nframes):
plots:-animate(plot, [2e-3*myload(x,t), x=0..3, thickness=1, filled=[color="Green"]], t=0..T, frames=nframes):
plots:-display([%%,%], size=[600,250]);

z3d;


 

A triple-span beam, moving load falling off the cantilever end

 

In this demo the load move across a multi-span beam with a cantilever section at the right.

As it skips past the cantilever end, the beam snaps back violently.

d := 0.4:  T := 8: nframes := 200:
myload := - max(0, -6*(x - t/2)*(d + x - t/2)/d^3):
sol := beamsolve([1,1,1/2], 10, 'T'=T, 'F'=myload, BC_right=[u_xx, u_xxx]):
sol:-animate(frames=nframes):
plots:-animate(plot, [1e-2*myload(x,t), x=0..3, thickness=1, filled=[color="Green"]], t=0..T, frames=nframes):
plots:-display([%%,%], size=[600,250]);


 


Download worksheet: euler-beam-with-method-of-lines.mw

 

Here is a little cute demo that shows how a cube may be paritioned into three congruent pyramids.  This was inspired by a Mathematica demo that I found in the web but I think this one's better :-)

A Cube as a union of three right pyramids

Here is an animated demo of the well-known fact that a cube may be partitioned

into three congruent right pyramids.

 

2020-05-21

restart;

with(plots):

with(plottools):

A proc to plot a general polyhedron.
V = [[x, y, z], [x, y, z], () .. (), [x, y, z]]                list of vertices
F = [[n__1, n__2, () .. ()], [n__1, n__2, () .. ()], () .. (), [n__1, n__2, () .. ()]]  list of faces

An entry "[`n__1`,`n__2`. ...]" in Fdescribes a face made of the vertices "V[`n__1`], V[`n__2`], ...," etc.

polyhedron := proc(V::list, F::list)
  seq(plottools:-polygon([seq( V[F[i][j]], j=1..nops(F[i]))]), i=1..nops(F));
  plots:-display(%);
end proc:

Define the vertices and faces of a pyramid:

v := [[0,0,0],[1,0,0],[1,1,0],[0,1,0],[0,0,1]];
f := [ [1,2,3,4], [5,2,3], [5,3,4], [1,5,4], [1,2,5] ];

[[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], [0, 0, 1]]

[[1, 2, 3, 4], [5, 2, 3], [5, 3, 4], [1, 5, 4], [1, 2, 5]]

Build three such pyramids:

P1 := polyhedron(v, f):
P2 := reflect(P1, [[1,0,0],[1,1,0],[1,0,1]]):
P3 := reflect(P1, [[0,1,0],[1,1,0],[0,1,1]]):

This is what we have so far:

display(P1,P2,P3, scaling=constrained);

Define an animation frame.  The parameter t goes from 0 to 1.

Any extra options are assumed to be plot3d options and are

passed to plots:-display.

frame := proc(t)
  plots:-display(
    P1,

    rotate(P2, Pi/2*t, [[1,1,0],[1,0,0]]),
    rotate(P3, Pi/2*t, [[0,1,0],[1,1,0]]),
    color=["Red", "Green", "Blue"], _rest);
end proc:

Animate:

display(frame(0) $40, seq(frame(t), t=0..1, 0.01), frame(1) $40,
  insequence, scaling=constrained, axes=none,
  orientation=[45,0,120], viewpoint=circleleft);

 

Download square-partitioned-into-pyramids.mw

 

 

Here we simulate the motion of a container with a flat bottom that can slide on a horizontal surface subject to dry friction (Coulomb friction).  Installed inside the container is an ordinary mass/spring/damper system where the mass slides horizontally.  We impart an initial velocity to the container.  That sets the mass into motion which then affects the container's motion.  Under certain conditions the container will undergo a stick-slip motion which is evident in the simulation.

This simulation very roughly approximates the motion of a partially filled bucket of water that slides on the floor when kicked.  The idea arose in a discussoin with Carl Love and mmcdara:
https://www.mapleprimes.com/posts/211677-Mass-Spring-Conveyor-Belt-And-Dry-Friction

In the animation below, the container is shown in dark color when it slides against the floor, and light color when it sticks.

Worksheet: slosh.mw

 

1 2 Page 1 of 2