Challenge

Python Program to Calculate Displacement of a Bar under Tension

EXPLICIT AND IMPLICIT METHODS TO CALCULATE DISPLACEMENT OF A BAR UNDER TENSION

Introduction:

Explicit and implicit methods are approaches used in numerical analysis for obtaining numerical approximations to the solutions of time-dependent ordinary and partial differential equations, as is required in computer simulations of physical processes.

Explicit methods calculate the state of a system at a later time from the state of the system at the current time, while implicit methods find a solution by solving an equation involving both the current state of the system and the later one.

Implicit and Explicit analysis differ in the approach to time increments. In Implicit analysis each time increment has to converge, but we can set pretty long time increments.

Explicit on the other hand doesn’t have to converge each increment, but for the solution to be accurate time increments must be super small.

In general, when we want to solve a dynamic problem, we are asking the solver to calculate the series of time increments, to see what is going on in the model. In each of those increments, time slightly increases. This of course also changes the load in the model. This is why we need to have a time-dependent chart for load. So the solver knows what load should be applied at which time increment.

To this extent, both implicit and explicit analysis does more or less the same thing. They divide the analysis time into small increments, and then analyze what is going on in our model one increment of time after another.

Objective:

Consider the case of a simple bar in tension. Suppose that the force in the bar is a nonlinear function of the displacement is given as `F=u^5+7u^2+4u`

From the force equation, stiffness of the bar is `K = 5u^4+14u+4`

The following are the objectives of the project,

=>To calculate displacement of a bar under axial tensile load

=>To solve the problem with both explicit and implicit methods using incremental load control scheme

=>To compare the explicit, implicit and exact results of the problem

Explicit analysis:

Explicit analysis works in a way, that we don’t have to converge each step.

There are no convergence criteria to check and no iterations.

Instead of verifying the global equilibrium, solver assumes that the equilibrium simply exists.This means that the solver goes straight into calculation of local finite element variables.It calculates all of the local finite element variables for given increment, and moves to the next one.

Time increment in explicit analysis is very short. It’s the time in which an elastic wave (i.e. impact wave) can travel through a single finite element of your model.

Implicit analysis:

Implicit analysis works in a way,that in each time increment, the global equilibrium in the model is established. This means that each increment has to converge (this is happening in iterations).

Since global equilibrium is verified at each time increments, those increments can be large.

Each time increment computes slowly, since iterations are needed to get to the global equilibrium.

Explicit scheme:

If the nonlinear force versus displacement relationship is not known, but the stiffness is known, it is possible to construct the graph of force versus displacement numerically.

It can be done using an incremental explicit load control scheme.

The following equation is solved using explicit method as follows,

`F=u^5+7u^2+4u`

Differentiating force with respect to displacement gives the stiffness(k) of the bar (since F = kx).

`k(u) = (dF)/ (du) = 5u^4+14u+4`

Here,three equal load increments (or steps) of `DeltaF = 1` unit each are used to load the tension bar.

The variables used are u for displacement, f for internal force in the bar, F for external force applied to the bar and k for stiffness. Incremental displacements or incremental externally applied forces are represented as `Deltau` or `DeltaF`, respectively.

`DeltaF =k .Deltau` This relation is used to find the incremental displacement.

Step -1

`u_0 = 0.0, ᐃF = 1, ᐃu_1 = (ᐃF)/(k(u_0)), u_1 = u_0 + ᐃu_1 = 0.25`

`F_(external)=DeltaF=1`

`F_(Internal)=u^5+7u^2+4u=1.4384` `(because u=u_2)`

Step - 2

`u_1 = 0.25, ᐃF = 1, ᐃu_2 = (ᐃF)/(k(u_1)), u_2 = u_1 + ᐃu_2 = 0.3829`

`F_(external)=DeltaF=2`

`F_(Internal)=u^5+7u^2+4u=2.5669` `(because u=u_2)`

Step - 3

`u_2 = 0.3829, ᐃF = 1, ᐃu_3 = (ᐃF)/(k(u_2)), u_3 = u_2 + ᐃu_3 = 0.4885`

`F_(external)=DeltaF=3`

`F_(Internal)=u^5+7u^2+4u=3.6532` `(because u=u_3)`

The following table summarizes the results for explicit analysis method.

It is evident from the results that external and internal forces are NOT in equilibrium because `F_(external)!=F_(Internal)`.

Implicit scheme:

An implicit analysis is the same as the explicit analysis, except that at the end of each step Newton-Raphson iterations are used to enforce equilibrium before moving to the next step.

Basically, an incremental force is applied to advance the solution forward at the beginning of a step. However, internal forces and external forces will not be in equilibrium unless the
stiffness is linear for the given step.

Hence, in order to achieve equilibrium, corrections must be made to the displacement.

This is accomplished by using Newton-Raphson iterations to minimize the residual, `R=F_(Internal)-F_(external)`

Expanding the residual as a Taylor series about the current displacement `u^j` gives

`R^(j+1) = R^j(u^j) + (dR(u^j))/ (du )deltau^(j+1) + ... = R^j + k(u^j)deltau^(j+1 )+ ...`

By neglecting higher order terms in the series, setting `R^(j+1) =0` and solving for `deltau^(j+1)` the following correction is obtained

`deltau^(j+1 )= −[k(u^j)]^(−1)*R^j`

Here, the iteration variable is j and it may take several iterations for the norm of the residual, R, to be reduced below the chosen tolerance criteria of 0.001.

The implicit analysis proceeds as follows

Step - 1

`u_0 = 0.0, ᐃF = 1, ᐃu_1 = (ᐃF)/(k(u_0)), u_1 = u_0 + ᐃu_1 = 0.25`

Residual `R = F_(Internal) - F_(External)`

On checking the residual, R > 0.001, we need to implement correction factor for this iteration. Hence we get a new updated displacement value `u_(updated) = u + δu`

The process of residual check is repeated for each iteration using the new updated u value, until we achieve force equilibrium.

Therefore, the updated u value = 0.18806

Step - 2

`u_1 = 0.18806, ᐃF = 1, ᐃu_2 = (ᐃF)/(k(u_1)), u_2 = u_1 + ᐃu_2 = 0.3386`

Residual `R = F_(Internal) - F_(External)`

On checking the residual, R > 0.001, we need to implement correction factor for this iteration. Hence we get a new updated displacement value `u_(updated) = u + δu`

The process of residual check is repeated for each iteration using the new updated u value, until we achieve force equilibrium.

Therefore, the updated u value = 0.3199

Step - 3

`u_2 = 0.3199, ᐃF = 1, ᐃu_3 = (ᐃF)/(k(u_2)), u_3 = u_2 + ᐃu_3 = 0.4371`

Residual `R = F_(Internal) - F_(External)`

On checking the residual, R > 0.001, we need to implement correction factor for this iteration. Hence we get a new updated displacement value `u_(updated) = u + δu`

The process of residual check is repeated for each iteration using the new updated u value, until we achieve force equilibrium.

Therefore, the updated u value = 0.4251

The following table summarizes the results for implicit analysis method.

It is evident from the results that external and internal forces are in equilibrium because `F_(external)=F_(Internal)`.

Comparison:

A plot of the results is shown in below figure.

Exact solution is calculated by having displacement, u value from 0 to 0.43, substituted in the force equation used for the analysis.

It is evident from the plot that the explicit analysis drifts from the exact solution.

The drift from the exact solution illustrates the lack of equilibrium between the internal and external forces. To correct for this problem an implicit analysis is required.

The Newton-Raphson iterations correct the incremental steps so that they land on the exact solution according to the specified tolerance.

Excellent agreement is achieved with just 3 increments and in each step only two Newton-Raphson iterations are required.

Conclusion:

Thus, a nonlinear analysis is illustrated using an incremental explicit and implicit procedure. The results are plotted for comparison.

The techniques demonstrated are for a load control scheme.Once satisfactory equilibrium is achieved, a new load increment is applied to advance the solution and the process is repeated.

As discussed, we can use both implicit and explicit methods to solve the same type of problem. The only difference is in approach to time increment.

The implicit analysis allows you to select how big the time increment should be. This increment will take some time to compute since it has to iterate for global equilibrium first. But we can make it reasonably big for our analysis.

Explicit time increments calculate really fast because they do not iterate for global equilibrium.

The debate on what type of solver is better depends upon the type of problem and accuracy we need.

Python program that solves a problem of a bar subjected to tension using explicit and implicit methods:

# Explicit and implicit analysis with three steps


# importing required libraries
import matplotlib.pyplot as plt
import numpy as np


# A function that defines force in the bar with respect to displacement
def F(u):

	# Equation of force
    f = u ** 5 + (7 * u ** 2) + (4 * u)
    return f


# A function that defines stiffness of the bar with respect to displacement 
def k(u):

	# Equation of stiffness found by differentiating force equation with respect to displacement
    K = (5 * u ** 4) + (14 * u) + 4
    return K


# ---------------Explicit scheme------------------

# an empty array that stores the values computed using explicit scheme
table_explicit = []


# A function that computes parameters using explicit method
def Explicit():
    print('-------------Explicit scheme--------------')
    Delta_F = 1				# load increment
    F_ext = []				# empty array to store values of external forces	
    F_int = []				# empty array to store values of internal forces
    
    # residual = internal force - external force
    Res = []				# empty array to store values of residual values

    # Step 1
    u_0 = 0					# assuming that initial displacement is zero
    Delta_u_1 = Delta_F / k(u_0)
    u_1 = u_0 + Delta_u_1
    F_ext.append(Delta_F)
    F_int.append(F(u_1))

    # Step 2
    Delta_u_2 = Delta_F / k(u_1)
    u_2 = u_1 + Delta_u_2
    F_ext.append(2 * Delta_F)
    F_int.append(F(u_2))

    # Step 3
    Delta_u_3 = Delta_F / k(u_2)
    u_3 = u_2 + Delta_u_3
    F_ext.append(3 * Delta_F)
    F_int.append(F(u_3))

    for i in range(0, len(F_ext)):
        R = F_int[i] - F_ext[i]			# residual = internal force - external force
        Res.append(R)

        print('Step', i + 1)
        print('------')
        print('External force  =', F_ext[i])
        print('Internal force =', F_int[i])
        print('Residual =', Res[i])
        print('\n')



    # forming a table that summarizes the explicit results
    table_explicit.append(1)
    table_explicit.append(u_1)
    table_explicit.append(F_ext[0])
    table_explicit.append(F_int[0])
    table_explicit.append(Res[0])

    table_explicit.append(2)
    table_explicit.append(u_2)
    table_explicit.append(F_ext[1])
    table_explicit.append(F_int[1])
    table_explicit.append(Res[1])

    table_explicit.append(3)
    table_explicit.append(u_3)
    table_explicit.append(F_ext[2])
    table_explicit.append(F_int[2])
    table_explicit.append(Res[2])


    # displaying explicit results in tabular form
    print('EXPLICIT METHOD RESULTS')
    print(
        '--------------------------------------------------------------------------------------------------------------------')
    print(
        '|     Steps      |     Updated u value     |     External force     |     Internal force     |        Residual     |')
    print(
        '--------------------------------------------------------------------------------------------------------------------')

    print('|             ', table_explicit[0], '|                   ', table_explicit[1], '|                     ',
          table_explicit[2],
          '|          ', table_explicit[3], '|       ', table_explicit[4], '|')
    print(
        '--------------------------------------------------------------------------------------------------------------------')
    print('|             ', table_explicit[5], '|      ', table_explicit[6], '|                     ',
          table_explicit[7],
          '|     ', table_explicit[8], '| ',
          table_explicit[9], '|')
    print(
        '--------------------------------------------------------------------------------------------------------------------')
    print('|             ', table_explicit[10], '|     ', table_explicit[11], '|                     ',
          table_explicit[12], '|    ', table_explicit[13],
          '| ', table_explicit[14], '|')
    print(
        '--------------------------------------------------------------------------------------------------------------------')


Explicit()

# ----------------------Implicit scheme--------------------

# an empty array that stores the values computed using explicit scheme
table_implicit = []


# A function that computes parameters using implicit method
def Implicit():
    print('\n')
    print('-------------Implicit scheme--------------')
    Delta_F = 1 		 # load increment
    tol = 0.001			 # tolerance


    # step 1
    u_0 = 0				 # assuming that initial displacement is zero
    del_1_u = 0			 # correction factor
    Delta_u_1 = Delta_F / k(u_0)

    iteration = 10		 # problem is solved for 10 iterations in each step
    u_step_1 = []		 # empty array that stores the displacement values computed at step 1 of implicit method
    u1 = u_0 + Delta_u_1
    u_step_1.append(u1)

    print('Step 1')
    print('------')
    for i in range(0, iteration):
        u_1 = u_step_1[0] + del_1_u
        u_step_1.append(u_1)
        Res = F(u_1) - Delta_F		# residual value 
        itr = i + 1
        print('External force = ', Delta_F)
        print('Internal force = ', F(u_1))
        print('Residual = ', Res)
        print('Updated u value = ', u_1)

        if Res < tol:
            print('Forces are in equilibrium')
            print('Iteration =', itr)
            break

        else:
            print('Forces are not in equilibrium. Hence Newton Raphson iterations are necessary')
            del_1_u = del_1_u - (Res / k(u_1))  # correction factor

            print('Iteration =', itr)
            print('\n')

    # forming a table that summarizes the implicit results of step 1
    table_implicit.append(1)
    table_implicit.append(u_1)
    table_implicit.append(Delta_F)
    table_implicit.append(F(u_1))
    table_implicit.append(Res)


    # step 2
    Delta_u_2 = Delta_F / k(u_1)
    del_2_u = 0
    u_step_2 = []
    u2 = u_1 + Delta_u_2
    u_step_2.append(u2)

    print('\n')
    print('Step 2')
    print('------')
    for i in range(0, iteration):
        u_2 = u_step_2[0] + del_2_u
        u_step_2.append(u_2)
        Res = F(u_2) - (2 * Delta_F)
        itr = i + 1
        print('External force = ', 2 * Delta_F)
        print('Internal force = ', F(u_2))
        print('Residual = ', Res)
        print('Updated u value = ', u_2)

        if Res < tol:
            print('Forces are in equilibrium')
            print('Iteration =', itr)
            break

        else:
            print('Forces are not in equilibrium. Hence Newton Raphson iterations are necessary')
            del_2_u = del_2_u - (Res / k(u_2))  # correction factor

            print('Iteration =', itr)
            print('\n')

    # forming a table that summarizes the implicit results of step 2
    table_implicit.append(2)
    table_implicit.append(u_2)
    table_implicit.append(2 * Delta_F)
    table_implicit.append(F(u_2))
    table_implicit.append(Res)


    # step 3
    Delta_u_3 = Delta_F / k(u_2)
    del_3_u = 0
    u_step_3 = []
    u3 = u_2 + Delta_u_3
    u_step_3.append(u3)
    print('u_3 = ', u3)

    print('\n')
    print('Step 3')
    print('------')
    for i in range(0, iteration):
        u_3 = u_step_3[0] + del_3_u
        u_step_3.append(u_3)
        Res = F(u_3) - (3 * Delta_F)
        itr = i + 1
        print('External force = ', 3 * Delta_F)
        print('Internal force = ', F(u_3))
        print('Residual = ', Res)
        print('Updated u value = ', u_3)

        if Res < tol:
            print('Forces are in equilibrium')
            print('Iteration =', itr)
            break

        else:
            print('Forces are not in equilibrium. Hence Newton Raphson iterations are necessary')
            del_3_u = del_3_u - (Res / k(u_2))  # correction factor

            print('Iteration =', itr)
            print('\n')

    print('\n')
    
    # forming a table that summarizes the implicit results of step 1
    table_implicit.append(3)
    table_implicit.append(u_3)
    table_implicit.append(3 * Delta_F)
    table_implicit.append(F(u_3))
    table_implicit.append(Res)

    
    # displaying implicit results in tabular form
    print('IMPLICIT METHOD RESULTS')
    print(
        '-------------------------------------------------------------------------------------------------------------------------')
    print(
        '|     Steps      |     Updated u value     |     External force     |     Internal force     |           Residual       |')
    print(
        '-------------------------------------------------------------------------------------------------------------------------')

    print('|             ', table_implicit[0], '|    ', table_implicit[1], '|                     ',
          table_implicit[2],
          '|    ', table_implicit[3], '|    ', table_implicit[4], '|')
    print(
        '-------------------------------------------------------------------------------------------------------------------------')
    print('|             ', table_implicit[5], '|      ', table_implicit[6], '|                     ',
          table_implicit[7],
          '|    ', table_implicit[8], '|  ',
          table_implicit[9], ' |')
    print(
        '-------------------------------------------------------------------------------------------------------------------------')
    print('|             ', table_implicit[10], '|    ', table_implicit[11], ' |                     ',
          table_implicit[12], '|    ', table_implicit[13],
          '|   ', table_implicit[14], '|')
    print(
        '-------------------------------------------------------------------------------------------------------------------------')


Implicit()


# plotting comparison between explicit ,implicit and exact results

# explicit result plot
plt.plot([0, table_explicit[1], table_explicit[6], table_explicit[11]],
         [0, table_explicit[2], table_explicit[7], table_explicit[12]], color='r', label='Explicit', linewidth=3)

# implicit result plot
plt.plot([0, table_implicit[1], table_implicit[6], table_implicit[11]],
         [0, table_implicit[2], table_implicit[7], table_implicit[12]], color='b', label='Implicit', linewidth=3)

# exact result plot
plt.plot(np.linspace(0, 0.43, 50), F(np.linspace(0, 0.43, 50)), color='g', label='Exact', linewidth=3)

plt.xlabel('Displacement, u')
plt.ylabel('Force, F')
plt.title('Comparison between Explicit, Implicit and Exact results')
plt.legend()
plt.show()
Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.