ENGN1300: Mechanics of Structures
 
FEM Truss Analysis Program Listing.

             Graphics Version



> restart:

# Finte Element Truss Analysis Program

#

#********** GIVE THE NAME OF THE INPUTFILE IN THE LINE BELOW ***********

#                    Use frontslash/ in place of backslash\

#                    Enclose the name in single backquotes`

#                        End the line with a colon:

#

infilename:=

`C:/Documents and Settings/laptop306/Desktop/tutorial.inp.txt`:

#

#*************************** THEN HIT RETURN ***************************

#

#***********************************************************************

#    load plotting and linear algebra maple packages

#

with(plots):with(linalg):with(plottools):

#

# define an output file name

#

lifn:=length(infilename):

outfilename:=cat(substring(infilename,1..lifn-8),`.out.txt`):

#

# ================= Read data from the input file ==================

#

     infile:=fopen(infilename,READ):

#

#    Title:

#

runtitle := readline(infile):

#

#    No. nodes and nodal coordinates

#

nnode := fscanf(infile,`%d`)[1]:

   coord := array(1..nnode,1..2):

    for i from 1 to nnode do

       coord[i,1] := fscanf(infile,`%f`)[1]:

       coord[i,2] := fscanf(infile,`%f`)[1]:

     od:

#

#    No. elements connectivity, and material data.

#        connect[i,1] and connect[i,2] hold the two joint numbers for the

#        ith member. connect[i,3] holds EA for that member

#

   nelem := fscanf(infile,`%d`)[1]:

   connect := array(1..nelem,1..3):

     for i from 1 to nelem do

       for j from 1 to 2 do

          connect[i,j] := fscanf(infile,`%d`)[1]:

       od:

       connect[i,3] := fscanf(infile,`%e`)[1]:

     od:

 

#

#    No. degrees of freedom with prescribed displacements; prescribed

#    displacements

#

   nfix := fscanf(infile,`%d`)[1]:

   fixnodes := array(1..nfix,1..3):

      for i from 1 to nfix do

#

# fixnodes[i,1] holds the number of the ith fixed node

# fixnodes[i,2] holds the direction (1 or 2)

# fixnodes[i,3] holds the valus of the prescribed displacement

#

       fixnodes[i,1] := fscanf(infile,`%d`)[1]:

       fixnodes[i,2] := fscanf(infile,`%d`)[1]:

       fixnodes[i,3] := fscanf(infile,`%e`)[1]:

      od:

#

#    No. loaded nodes, with the loads

#

    nload := fscanf(infile,`%d`)[1]:

    loads := array(1..nload,1..3):

#

#    Node number of ith loaded node is in loads[i,1]

#    F1 and F2 for the ith loaded node are in loads[i,2] and loads[i,3]

#

       for i from 1 to nload do

         loads[i,1] := fscanf(infile,`%d`)[1]:

         loads[i,2] := fscanf(infile,`%e`)[1]:

         loads[i,3] := fscanf(infile,`%e`)[1]:

       od:

    fclose(infile):

#

#********************************GRAPHICS************************************************

#

#    Plot the undeformed mesh

#

elplot:=[seq([[coord[connect[i,1],1],coord[connect[i,1],2]],

             [coord[connect[i,2],1],coord[connect[i,2],2]]],                                 i=1..nelem)]:

pnodes:=textplot({seq([coord[nn,1],coord[nn,2],convert(nn,string)],nn=1..nnode)},

       font=[TIMES,BOLD,16]):

pels:=textplot({seq([(coord[connect[ne,1],1]+coord[connect[ne,2],1])/2,

                     (coord[connect[ne,1],2]+coord[connect[ne,2],2])/2,convert(ne,string)],

                      ne=1..nelem)},font=[HELVETICA,12]):

pm:=plot(elplot,axesfont=[TIMES,ROMAN,6],

color=magenta,labelfont=[TIMES,ROMAN,12], titlefont=[TIMES,ROMAN,14],title=cat(runtitle,`: Mesh`),

thickness=3,labels=[`x1`,`x2`],scaling=constrained):

display(pm,pnodes,pels);

#

#  Plot loads and BC

#

#  Scale the load vector by max element length*max load magnitude*.2

#

maxlength:= max(seq(sqrt((coord[connect[ie,1],1]-coord[connect[ie,2],1])^2+

     (coord[connect[ie,1],2]-coord[connect[ie,2],2])^2),ie=1..nelem)):

maxf:=max(seq(sqrt(loads[ii,2]^2+loads[ii,3]^2),ii=1..nload)):

loadscale:=0.2*maxlength/(maxf+0.00001*maxlength):

#

# graphics of laod vectors

#

loadarrows:=seq(arrow([coord[loads[il,1],1],coord[loads[il,1],2]],          [coord[loads[il,1],1]+loadscale*loads[il,2],coord[loads[il,1],2]+loadscale*loads[il,3]],

                    .02, .1, .3, color=green),il=1..nload):

#

# Scale the displacement arrows by max element length*max presc. displacement*.2

#

maxd:=max(seq(abs(fixnodes[ii,3]),ii=1..nfix)):

bcscale:=0.2*maxlength/(maxd+0.00001*maxlength):

 

#

# graphics of BC vectors

#

bcarrows:=seq(arrow(

          [coord[fixnodes[il,1],1]-(2-fixnodes[il,2])*(fixnodes[il,3]+.05*maxlength),

           coord[fixnodes[il,1],2]-(fixnodes[il,2]-1)*(fixnodes[il,3]+.05*maxlength)],

           [coord[fixnodes[il,1],1],coord[fixnodes[il,1],2]],.01,.03,1-bcscale*fixnodes[il,3],                             color=blue),il=1..nfix):

#

# graphics of load labels

#

plls:=textplot({seq([(coord[loads[il,1],1]+loadscale*loads[il,2]/2,coord[loads[il,1],2]+loadscale*loads[il,3]/2,

substring(convert(sqrt(loads[il,2]^2+loads[il,3]^2),string),1..4))],

                      il=1..nload)},font=[HELVETICA,12]):

#

display(plls,pm,bcarrows,loadarrows,title=cat(runtitle,`: Load and BC`));

#

#********************************END OF GRAPHICS***********************************

#

Warning, the name changecoords has been redefined

 

Warning, the protected names norm and trace have been redefined and unprotected

 

Warning, the name arrow has been redefined

 

> #

#================ ELEMENT STIFFNESS MATRIX ===================

#

elstif := proc (xa,ya,xb,yb,EA)

    local elstif, nx, ny, length;

#

#     Define the element length and direction vector

#

   length := sqrt((xa-xb)*(xa-xb)+(ya-yb)*(ya-yb));

#  

   nx := (xb-xa)/length;

   ny := (yb-ya)/length;

  

#

#     Define the element stiffness

#

     elstif := evalm((EA/length)*array(1..4,1..4,

                 [[nx*nx,nx*ny,-nx*nx,-nx*ny],

                  [ny*nx,ny*ny,-ny*nx,-ny*ny],

                  [-nx*nx,-nx*ny,nx*nx,nx*ny],

                  [-ny*nx,-ny*ny,ny*nx,ny*ny]]));

end:

#

#===========Assemble the global stiffness matrix==============

#

Stif := array(1..2*nnode,1..2*nnode):

   for i from 1 to 2*nnode do

     for j from 1 to 2*nnode do

       Stif[i,j] := 0.0:

     od:

    od:

#

#   Loop over all the elements

#

for lmn from 1 to nelem do

#

#   Set up the stiffness for the current element

#

    a := connect[lmn,1]:

    b := connect[lmn,2]:

    EA := connect[lmn,3]:

    k := array(1..4,1..4):

    k:=elstif(coord[a,1],coord[a,2],coord[b,1],coord[b,2],EA):

#

#   Add the current element stiffness to the global stiffness

#

    for i from 1 to 2 do

      for ii from 1 to 2 do

        for j from 1 to 2 do

          for jj from 1 to 2 do

            rw := 2*(connect[lmn,i]-1)+ii:

            cl := 2*(connect[lmn,j]-1)+jj:       

            Stif[rw,cl] := Stif[rw,cl] + k[2*(i-1)+ii,2*(j-1)+jj]:

           od:

         od:

       od:

     od:

  od:

#

# ==================== Assemble global residual vector ============

#

#   Define the residual

#

    resid := array(1..2*nnode):

    for i from 1 to 2*nnode do

      resid[i] := 0.:

    od:

#

#   Loop loaded nodes

#

    for i from 1 to nload do

      a := loads[i,1]:

      f1 := loads[i,2]:

      f2 := loads[i,3]:

      resid[2*a-1] := resid[2*a-1] + f1:

      resid[2*a] :=  resid[2*a] + f2:

      od:

#

#   Modify the global stiffness and residual to include constraints

#

    for i from 1 to nfix do

       rw := 2*fixnodes[i,1]+fixnodes[i,2]-2:

       for j from 1 to 2*nnode do

         resid[j] := resid[j] - Stif[j,rw]*fixnodes[i,3]:        

         Stif[rw,j] := 0:

         Stif[j,rw] := 0:

     od;

       Stif[rw,rw] := 1.0:

       resid[rw] := fixnodes[i,3]:

     od:

#

# ================== Solve the FEM equations ===================

#

u := linsolve(Stif,resid):

#

#     Define a procedure to calculate the element strains

#

elstrain := proc (xa,ya,xb,yb,uax,uay,ubx,uby)

    local elstrain, nx, ny, length, uel;

#

#   length and direction vector for the element

#

length := sqrt((xa-xb)*(xa-xb)+(ya-yb)*(ya-yb));

#  

   nx := (xb-xa)/length;

   ny := (yb-ya)/length;

#

#     Element displacement vector

#

   uel := array(1..4,[uax,uay,ubx,uby]);

#

#     Element strains

#

   elstrain := ((ubx-uax)*nx+(uby-uay)*ny)/length;

end:

# 

#      compute element forces and strains:

#

for lmn from 1 to nelem do

      a := connect[lmn,1]:

      b := connect[lmn,2]:

      EA := connect[lmn,3]:

      xa := coord[a,1]:

      ya := coord[a,2]:

      xb := coord[b,1]:

      yb := coord[b,2]:

      uxa := u[2*a-1]:

      uya := u[2*a]:

      uxb := u[2*b-1]:

      uyb := u[2*b]:

      Strain[lmn] := elstrain(xa,ya,xb,yb,uxa,uya,uxb,uyb):

      Force[lmn]:=EA*Strain[lmn];

    od:   

#

#********************************GRAPHICS*****************************************

#    

#=====Plot the deformed mesh===

#

#=====Displacements are scaled by 0.1*maximum displacement*maximum element length

#   

maxu:=max(seq(abs(u[ii]),ii=1..2*nnode)):

plotscale:=0.1*maxlength/maxu:

print(`Displacements scaled by:`,plotscale);

#

dcoord:=array(1..nnode,1..2):

    for a from 1 to nnode do

      xa := coord[a,1]:

      ya := coord[a,2]:

      uxa := u[2*a-1]:

      uya := u[2*a]:

      dcoord[a,1]:=xa+plotscale*uxa:

      dcoord[a,2]:=ya+plotscale*uya:

    od:

defplot:=[seq([[dcoord[connect[i,1],1],dcoord[connect[i,1],2]],

             [dcoord[connect[i,2],1],dcoord[connect[i,2],2]]],                                 i=1..nelem)]:

#

pd:=plot(defplot,axesfont=[TIMES,ROMAN,10],

color=green,labelfont=[TIMES,ROMAN,14], titlefont=[TIMES,BOLD,16],title=`Truss Mesh`,

thickness=3,labels=[`x1`,`x2`],scaling=constrained,title=cat(runtitle, `: Deformation`)):

#

dloadarrows:=seq(arrow([dcoord[loads[il,1],1],dcoord[loads[il,1],2]],

          [dcoord[loads[il,1],1]+loadscale*loads[il,2],dcoord[loads[il,1],2]+loadscale*loads[il,3]],

                    .02, .1, .3, color=green),il=1..nload):

#

# Scale the bc vector by max element length*max presc. displacement*.2

#

maxd:=max(seq(abs(fixnodes[ii,3]),ii=1..nfix)):

bcscale:=0.2*maxlength/(maxd+0.00001*maxlength):

 

#

# graphics of bc

#

dbcarrows:=seq(arrow(

          [dcoord[fixnodes[il,1],1]-(2-fixnodes[il,2])*(fixnodes[il,3]+.05*maxlength),

           dcoord[fixnodes[il,1],2]-(fixnodes[il,2]-1)*(fixnodes[il,3]+.05*maxlength)],

           [dcoord[fixnodes[il,1],1],dcoord[fixnodes[il,1],2]],.01,.03,1-bcscale*fixnodes[il,3],                             color=blue),il=1..nfix):

#

display(pd,pm,dbcarrows,dloadarrows);

#

#====Display element forces graphically

#

#

pforce:=textplot({seq([(coord[connect[ne,1],1]+coord[connect[ne,2],1])/2,(coord[connect[ne,1],2]+coord[connect[ne,2],2])/2, convert(evalf(Force[ne],3),string)],ne=1..nelem)},font=[HELVETICA,14]):

#

display({pm,pnodes,pforce},titlefont=[TIMES,BOLD,16],title=cat(runtitle,`: Forces`),

thickness=3,scaling=constrained,axes=none);

#

#******************************** END OF GRAPHICS ***********************************

#

#

#    Print nodal displacements, element strains and forces

#

outfile:=fopen(outfilename,WRITE):

#

fprintf(outfile, `%s\n`,runtitle):

fprintf(outfile,`%s %3d %3d\n` ,`Number of Nodes and Elements:`,nnode, nelem):

fprintf(outfile,`%s\n`,`Node#    x1     x2`):

   for i from 1 to nnode do

      fprintf(outfile,`%5d %9.4f  %9.4f\n`,

                  i,coord[i,1],coord[i,2]):

   od:

fprintf(outfile,`%s\n`,`El#   Node 1  Node 2     EA`):

   for i from 1 to nelem do

      fprintf(outfile,`%4d %10d  %10d %9.4f\n`,

                  i,connect[i,1],connect[i,2],connect[i,3]):

   od:

fprintf(outfile,`%s\n`,`Fixed Node#  DOF  Value`):

   for i from 1 to nfix do

      fprintf(outfile,`%9d %12d %10.4f\n`,

                  fixnodes[i,1],fixnodes[i,2],fixnodes[i,3]):

   od:

fprintf(outfile,`%s\n`,`Loaded Node#    P1       P2`):

   for i from 1 to nload do

      fprintf(outfile,`%9d %13.4f %9.4f\n`,

                  loads[i,1],loads[i,2],loads[i,3]):

   od:

fprintf(outfile,`%s\n`,` `):

fprintf(outfile,`%s\n`,`*********************************`):

fprintf(outfile,`%s\n`,` `):

fprintf(outfile,`%s\n`,`Nodal Displacements:`):

fprintf(outfile,`%s\n`,` Node    u1       u2`):

   for i from 1 to nnode do

      fprintf(outfile,`%3d %8.4f %8.4f\n`,i,u[2*i-1],u[2*i]):

   od:

fprintf(outfile,`%s\n`,`Strains and Forces:`):

fprintf(outfile,`%s\n`,`Element   Strain     Force`):

   for i from 1 to nelem do

      fprintf(outfile,`%3d %9.4f %9.4f\n`,i,Strain[i],Force[i]):

   od:

fclose(outfile):

print(`End`);