function FEM_truss(data,A) # FEM solver for truss elements # Author: JV Carstensen, CEE, MIT (JK Guest, Civil Eng, JHU) # Revised: Aug 22 2017, JVC # Revised: Amira Abdel-Rahman # ======================================================================= # ---- READ IN DATA ----------------------------------------------------- # read in external file E,f,dis,idb,ien,ndf,nel,nen,nnp,nsd,xn,len,Ke,Te= data; g=zeros(size(dis)) g.=dis # ---- NUMBER THE EQUATIONS --------------------------------------------- # line 380 id,neq = number_eq(idb,ndf,nnp); # ---- FORM THE ELEMENT STIFFNESS MATRICES ------------------------------ # line 324 nee = ndf*nen; # number of element equations Ke = zeros(nee,nee,nel); Te = zeros(nen*1,nen*nsd,nel); # *1 is specific to truss for i = 1:nel Ke[:,:,i],Te[:,:,i] = Ke_truss(A[i],E[i],ien[:,i],nee,nsd,xn); end # display("Element Stiffness Matrix") # display(Ke) # ---- PERFORM GLOBAL TO LOCAL MAPPING ---------------------------------- # line 237 LM = zeros(nee,nel); for i = 1:nel LM[:,i] = get_local_id(id,ien[:,i],ndf,nee,nen); end # ---- IF THERE IS FREE DEGREES OF FREEDOM, THEN SOLVE THE EQUILIBRIUM -- if (neq > 0) # get global force vector (line 275) F = globalF(f,g,id,ien,Ke,LM,ndf,nee,nel,nen,neq,nnp); # solve Kd - F = 0 (line 521) d,K = solveEQ(F,LM,Ke,nee,nel,neq); end # display("F") # display(F) # ---- POST-PROCESS THE RESULTS ----------------------------------------- # line 419 dcomp,axial,stress,strain,Fe = post_processing(A,d,E,g,id,ien,Ke,ndf,nee,nel,nen,nnp,Te); # display("dcomp") # display(dcomp) # display("axial") # display(axial) # display("stress") # display(stress) # ---- COMPUTE REACTION FORCES ------------------------------------------ # line 482 Rcomp,idr = reactions(idb,ien,Fe,ndf,nee,nel,nen,nnp); # display("Rcomp") # display(Rcomp) # ---- PLOT THE STRUCTURE ----------------------------------------------- # read in external file # set the plot factor for the thickness of the truss elements # plot_fac_bar = 1/A[i]; # A_min = 0; # plot_truss(A,A_min,f,idr,ien,nel,nnp,nsd,plot_fac_bar,xn); return K,F,d,stress,dcomp,g # ======================================================================= end # ======================================================================= function add_d2dcomp(dcomp,d,id,ndf,nnp) # function that adds the displacements of the free degrees of freedom to # the nodal displacements # ----------------------------------------------------------------------- # dcomp(ndf,nnp) = nodal displacements # d(neq,1) = displacement at free degrees of freedom # id(ndf,nnp) = equation numbers of degrees of freedom # ndf = number of degrees of freedom per node # nnp = number of nodal points #------------------------------------------------------------------------ # loop over nodes and degrees of freedom for n=1:nnp for i=1:ndf # if it is a free dof then add the global displacement if (id[i,n]>0) dcomp[Int(i),Int(n)] = dcomp[Int(i),Int(n)]+d[Int(id[Int(i),Int(n)])]; end end end return dcomp end # ======================================================================= function add_loads_to_force(F,f,id,ndf,nnp) # function that adds nodal forces to the global force vector # ----------------------------------------------------------------------- # F(neq,1) = global force vector # f(ndf,nnp) = prescribed nodal forces # id(ndf,nnp) = equation numbers of degrees of freedom # ndf = number of degrees of freedom per node # nnp = number of nodal points #------------------------------------------------------------------------ # loop over nodes and degrees of freedom for n = 1:nnp for i = 1:ndf # get the global equation number M = id[i,n]; # if free degree of freedom, then add nodal load to global force # vector if (M > 0) F[Int(floor(M))] = F[Int(floor(M))] + f[Int(floor(i)),Int(floor(n))]; end end end return F end # ======================================================================= function addforce(F,Fe,LM,nee) # function that adds element forces to the global force vector # ----------------------------------------------------------------------- # F(neq,1) = global force vector # Fe(nee,1) = element force vector # LM(nee,nel) = global to local map for the element # nee = number of element equations # ======================================================================= # loop over rows of Fe for i = 1:nee # get the global equation number for local equation i M = LM[i]; # if free dof (eqn number > 0) add to F vector if (M > 0) F[Int(M)]=F[Int(M)]+Fe[Int(i)]; end end return F end # ======================================================================= function get_de_from_dcomp(dcomp,ien,ndf,nen) # extracts element displacement vector from complete displacement vector #------------------------------------------------------------------------ # dcomp(ndf,nnp) = nodal displacements # ien(nen,1) = element connectivity # ndf = number of degrees of freedom per node # nen = number of element equations # # de(nen,1) = element displacements # #------------------------------------------------------------------------ de = zeros((nen-1)*ndf+ndf,1); # loop over number of element nodes for i = 1:nen # loop over number of degrees of freedom per node for j = 1:ndf # get the local element number and place displacement in de leq = (i-1)*ndf+j; de[leq] = dcomp[j,Int(floor(ien[i]))]; end end return de end # ======================================================================= function get_local_id(id,ien,ndf,nee,nen) # functions that performs the global to local mapping of equation numbers # ----------------------------------------------------------------------- # id(ndf,nnp) = equation numbers of degrees of freedom # ien(nen,1) = element connectivity # ndf = number of degrees of freedom per node # nee = number of element equations # nen = number of element equations # # LM(nee,1) = global to local map for element # ======================================================================= # initialize global-local mapping matrix LM = zeros(nee,1); # initialize local equation number counter k = 0; # loop over element nodes for i = 1:nen # loop over degrees of freedom at each node for j = 1:ndf # update counter and prescribe global equation number k = k+1; LM[k] = id[j,Int(floor(ien[i]))]; end end return LM end # ======================================================================= function globalF(f,g,id,ien,Ke,LM,ndf,nee,nel,nen,neq,nnp) # function that assembles the global load vector # ----------------------------------------------------------------------- # id(ndf,nnp) = equation numbers of degrees of freedom # f(ndf,nnp) = prescribed nodal forces # g(ndf,nnp) = prescribed nodal displacements # ien(nen,nel) = element connectivities # Ke(nee,nee,nel) = element stiffness matrices # ndf = number of degrees of freedom per node # nee = number of element equations # nel = number of elements # nen = number of element equations # neq = number of equations # nnp = number of nodal points # # F(neq,1) = global force vector # ======================================================================= # initialize F = zeros(neq,1); # Insert applied loads into F F = add_loads_to_force(F,f,id,ndf,nnp); # Compute forces from applied displacements (ds~=0) and insert into F Fse = zeros(nee,nel); # loop over elements for i = 1:nel # get dse for current element dse = get_de_from_dcomp(g,ien[:,i],ndf,nen); # compute element force Fse[:,i] = -Ke[:,:,i]*dse; # assemble elem force into global force vector F = addforce(F,Fse[:,i],LM[:,i],nee); end return F end # ======================================================================= function Ke_truss(A,E,ien,nee,nsd,xn) # function that computes the global element stiffness matrix for a truss # element # ----------------------------------------------------------------------- # A(1,1) = cross-sectional area of elements # E(1,1) = Young's modulus of elements # ien(nen,1) = element connectivity # nee = number of element equations # nsd = number of spacial dimensions # xn(nsd,nnp) = nodal coordinates # # Ke(nee,nee,1) = global element stiffness matrix # Te(nee,nee,1) = global to local transformation matrix for element # ======================================================================= # form vector along axis of element using nodal coordinates v = xn[:,Int(floor(ien[2]))]-xn[:,Int(floor(ien[1]))]; # compute the length of the element Le = norm(v,2); # rotation of parent domain # rot=[ cos(theta_x) cos(theta_y) cos(theta_z) ]' rot = v/Le; # local element stiffness matrix ke = E*A/Le*[ 1 -1 -1 1 ]; # Transformation matrix: global to local coordinate system if (nsd == 2) # 2D case # truss Te is nen x ndf*nen array Te = [ rot[1] rot[2] 0 0 0 0 rot[1] rot[2] ]; elseif (nsd == 3) # 3D case # Truss Te is nen x ndf*nen array Te = [ rot[1] rot[2] rot[3] 0 0 0 0 0 0 rot[1] rot[2] rot[3] ]; end # compute the global element stiffness matrix Ke = zeros(nee,nee); Ke = Te'*ke*Te; return Ke,Te end # ======================================================================= function number_eq(idb,ndf,nnp) # function that numbers the unknown degrees of freedom (equations) # ----------------------------------------------------------------------- # idb(ndf,nnp) = 1 if the degree of freedom is prescribed, 0 otherwise # ndf = number of degrees of freedom per node # nnp = number of nodal points # # id(ndf,nnp) = equation numbers of degrees of freedom # neq = number of equations (tot number of degrees of freedom) # ======================================================================= # initialize id and neq id = zeros(ndf,nnp); neq = 0; # loop over nodes for n = 1:nnp # loop over degrees of freedom for i = 1:ndf if idb[i,n] == 0 # udate # of equations neq = neq + 1; # if no prescribed displacement at dof i of node n # => give an equation # different from 0 id[i,n] = neq; end end end return id,neq end # ======================================================================= function post_processing(A,d,E,g,id,ien,Ke,ndf,nee,nel,nen,nnp,Te) # function that performs post processing for truss elements # ----------------------------------------------------------------------- # A(nel,1) = cross-sectional area of elements # d(neq,1) = displacements at free degrees of freedom # E(nel,1) = Young's modulus of elements # g(ndf,nnp) = prescribed nodal displacements # id(ndf,nnp) = equation numbers of degrees of freedom # ien(nen,nel) = element connectivities # Ke(nee,nee,nel) = element stiffness matrices # ndf = number of degrees of freedom per node # nee = number of element equations # nel = number of elements # nen = number of element equations # nnp = number of nodes # Te(nee,nee,nel) = element transformation matrices # # dcomp(ndf,nnp) = nodal displacements # axial(nel,1) = axial element forces # stress(nel,1) = element stresses # strain(nel,1) = element strains # Fe(nee,nel) = element forces # ======================================================================= # get the total displacement of the structure in matrix form dcomp(nsd,nnp) dcomp = add_d2dcomp(g,d,id,ndf,nnp); # initalize evaluation of global element forces Fe, local element forces # fe, axial forces, element stresses and strains Fe = zeros(nee,nel); de = zeros(nee,nel); fe = zeros(1*nen,nel); # element local force vector axial = zeros(nel,1); stress = zeros(nel,1); strain = zeros(nel,1); # element axial, stress, strain # loop over elements for i=1:nel # get the element displacaments de[:,i] = get_de_from_dcomp(dcomp,ien[:,i],ndf,nen); # compute the element forces Fe[:,i] = Ke[:,:,i]*de[:,i]; # transform Fe to the local coordinate system fe[:,i] = Te[:,:,i]*Fe[:,i]; # Compute the axial force, stress, strain axial[i] = fe[2,i] ; # Use second entry for truss element stress[i] = axial[i]/A[i]; strain[i] = stress[i]/E[i]; end # display("Fe") # display(Fe) return dcomp,axial,stress,strain,Fe end # ======================================================================= function reactions(idb,ien,Fe,ndf,nee,nel,nen,nnp) # function that computes the reaction forces on the structure # ----------------------------------------------------------------------- # idb(ndf,nnp) = 1 if the degree of freedom is prescribed, 0 otherwise # ien(nen,nel) = element connectivities # Fe(nee,nel) = element forces # ndf = number of degrees of freedom per node # nee = number of element equations # nel = number of elements # nen = number of element equations # nnp = number of nodes # # Rcomp(ndf,nnp) = nodal reactions # idbr(ndf,nnp) = 0 if the degree of freedom is prescribed, otherwise # ======================================================================= # switch BC marker and number the equations for the reaction forces idbr = 1 .- idb; idr,neqr = number_eq(idbr,ndf,nnp); # assemble reactions R from element force vectors Fe R = zeros(neqr,1); for i = 1:nel LMR = get_local_id(idr,ien[:,i],ndf,nee,nen); R = addforce(R,Fe[:,i],LMR,nee); end # organize the reactions in matrix array Rcomp(ndf,nnp) Rcomp = zeros(ndf,nnp); Rcomp = add_d2dcomp(Rcomp,R,idr,ndf,nnp); return Rcomp,idr end # ======================================================================= function addstiff(K,Ke,LM,nee) # function that solves the equilibrium condition # ----------------------------------------------------------------------- # K(neq,neq) = global stiffness matrix # Ke(nee,nee,1) = element stiffness matrix # LM(nee,nel) = global to local map for the element # nee = number of element equations # ======================================================================= # loop over rows of Ke for i =1:nee # loop over columns of Ke for j = 1:nee Mr = LM[i]; Mc = LM[j]; if(Mr > 0 && Mc > 0) # if equation #'s are non-zero add element contribution to the # stiffness matrix K[Int(Mr),Int(Mc)] = K[Int(Mr),Int(Mc)] +Ke[Int(i),Int(j)]; end end end return K end # ======================================================================= function solveEQ(F,LM,Ke,nee,nel,neq) # function that solves the equilibrium condition # ----------------------------------------------------------------------- # F(neq,1) = global force vector # LM(nee,nel) = global to local maps # Ke(nee,nee,nel) = element stiffness matrices # nee = number of element equations # nel = number of elements # neq = number of equations # # d(neq,1) = displacements at free degrees of freedom # ======================================================================= # assemble global stiffness matrix # K = zeros(neq,neq); # Use 'sparse' for more efficient memory usage K=spzeros(neq,neq) for i = 1:nel K = addstiff(K,Ke[:,:,i],LM[:,i],nee); end # display("K") # display(K) # solve the equlibrium d = K\F; # display("d") # display(d) return d,K end # ======================================================================= # ======================================================================= function data_truss() # ----------------------------------------------------------------------- # A(nel,1) = cross-sectional area of elements # E(nel,1) = Young's modulus of elements # f(ndf,nnp) = prescribed nodal forces # g(ndf,nnp) = prescribed nodal displacements # idb(ndf,nnp) = 1 if the degree of freedom is prescribed, 0 otherwise # ien(nen,nel) = element connectivities # ndf = number of degrees of freedom per node # nel = number of elements # nen = number of element equations # nnp = number of nodes # nsd = number of spacial dimensions # xn(nsd,nnp) = nodal coordinates # ======================================================================= # ---- MESH ------------------------------------------------------------- nsd = 2; # number of spacial dimensions ndf = 2; # number of degrees of freedom per node nen = 2; # number of element nodes nel = 3; # number of elements nnp = 3; # number of nodal points # ---- NODAL COORDINATES ------------------------------------------------ # xn(i,N) = coordinate i for node N # N = 1,...,nnp # i = 1,...,nsd # ----------------------------------------------------------------------- xn = zeros(nsd,nnp); xn[1:2,1] = [ 0 0]'; xn[1:2,2] = [ 4/tand(30) 4]'; xn[1:2,3] = [ 4+4/tand(30) 0]'; # ---- NODAL COORDINATES ------------------------------------------------ # ien(a,e) = N # N: global node number - N = 1,...,nnp # e: element number - e = 1,...,nel # a: local node number - a = 1,...,nen # ----------------------------------------------------------------------- ien = zeros(nen,nel); ien[1:2,1] = [1 2]' ; ien[1:2,2] = [2 3]' ; ien[1:2,3] = [3 1]' ; # ---- MATERIAL PROPERTIES ---------------------------------------------- # E(e) = E_mat # e: element number - e = 1,...,nel # ----------------------------------------------------------------------- E_mat = 200; # Young's modulus # lbf/in^2 E = E_mat*ones(nel,1); # ---- GEOMETRIC PROPERTIES --------------------------------------------- # A(e) = A_bar # e: element number - e = 1,...,nel # ----------------------------------------------------------------------- A = 1e3*[15; 20; 18]; # mm^2 # ---- BOUNDARY CONDITIONS ---------------------------------------------- # prescribed displacement flags (essential boundary condition) # # idb(i,N) = 1 if the degree of freedom i of the node N is prescribed # = 0 otherwise # # 1) initialize idb to 0 # 2) enter the flag for prescribed displacement boundary conditions # ----------------------------------------------------------------------- idb = zeros(ndf,nnp); idb[:,1].=1; idb[2,3]=1; # ---- BOUNDARY CONDITIONS: PRESCRIBED NODAL DISPLACEMENTS -------------- # g(i,N) = prescribed displacement magnitude # N = 1,...,nnp # i = 1,...,nsd # # 1) initialize g to 0 # 2) enter the values # ----------------------------------------------------------------------- g = zeros(ndf,nnp); # ---- BOUNDARY CONDITIONS: PRESCRIBED NODAL FORCES --------------------- # f(i,N) = prescribed force magnitude # N = 1,...,nnp # i = 1,...,nsd # # 1) initialize f to 0 # 2) enter the values # ----------------------------------------------------------------------- P = 500e3; # lbf f = zeros(ndf,nnp); f[1,2] = P*cosd(40); f[2,2] = P*sind(40); return A,E,f,g,idb,ien,ndf,nel,nen,nnp,nsd,xn end # ======================================================================= function data_truss2(A) # ----------------------------------------------------------------------- # A(nel,1) = cross-sectional area of elements # E(nel,1) = Young's modulus of elements # f(ndf,nnp) = prescribed nodal forces # g(ndf,nnp) = prescribed nodal displacements # idb(ndf,nnp) = 1 if the degree of freedom is prescribed, 0 otherwise # ien(nen,nel) = element connectivities # ndf = number of degrees of freedom per node # nel = number of elements # nen = number of element equations # nnp = number of nodes # nsd = number of spacial dimensions # xn(nsd,nnp) = nodal coordinates # ======================================================================= # ---- MESH ------------------------------------------------------------- nsd = 2; # number of spacial dimensions ndf = 2; # number of degrees of freedom per node nen = 2; # number of element nodes nel = 17; # number of elements nnp = 10; # number of nodal points # ---- NODAL COORDINATES ------------------------------------------------ # xn(i,N) = coordinate i for node N # N = 1,...,nnp # i = 1,...,nsd # ----------------------------------------------------------------------- L= 30.0/4.0;#*0.3048; H= 10.0;#*0.3048; xn = zeros(nsd,nnp); xn[1:2, 1] = [ 0 0]';# 1 xn[1:2, 2] = [ L 0]';# 2 xn[1:2, 3] = [ 2*L 0]';# 3 xn[1:2, 4] = [ 3*L 0]';# 4 xn[1:2, 5] = [ 4*L 0]';# 5 xn[1:2, 6] = [ 0 -H]';# 6 xn[1:2, 7] = [ L -H]';# 7 xn[1:2, 8] = [ 2*L -H]';# 8 xn[1:2, 9] = [ 3*L -H]';# 9 xn[1:2,10] = [ 4*L -H]';# 10 # ---- NODAL COORDINATES ------------------------------------------------ # ien(a,e) = N # N: global node number - N = 1,...,nnp # e: element number - e = 1,...,nel # a: local node number - a = 1,...,nen # ----------------------------------------------------------------------- ien = zeros(nen,nel); ien[1:2,1] = [1 2]' ;# ien[1:2,2] = [2 3]' ;# ien[1:2,3] = [3 4]' ;# ien[1:2,4] = [4 5]' ;# ien[1:2,5] = [6 7]' ;# ien[1:2,6] = [7 8]' ;# ien[1:2,7] = [8 9]' ;# ien[1:2,8] = [9 10]' ;# ien[1:2, 9] = [1 6]' ;# ien[1:2,10] = [2 6]' ;# ien[1:2,11] = [2 7]' ;# ien[1:2,12] = [2 8]' ;# ien[1:2,13] = [3 8]' ;# ien[1:2,14] = [4 8]' ;# ien[1:2,15] = [4 9]' ;# ien[1:2,16] = [4 10]' ;# ien[1:2,17] = [5 10]' ;# # ---- MATERIAL PROPERTIES ---------------------------------------------- # E(e) = E_mat # e: element number - e = 1,...,nel # ----------------------------------------------------------------------- E_mat = 29000*1000; # Young's modulus # lbf/in^2 E = E_mat*ones(nel,1); # ---- GEOMETRIC PROPERTIES --------------------------------------------- # A(e) = A_bar # e: element number - e = 1,...,nel # ----------------------------------------------------------------------- #A = ones(nel); #A[:] .= 400; # mm^2 # ---- BOUNDARY CONDITIONS ---------------------------------------------- # prescribed displacement flags (essential boundary condition) # # idb(i,N) = 1 if the degree of freedom i of the node N is prescribed # = 0 otherwise # # 1) initialize idb to 0 # 2) enter the flag for prescribed displacement boundary conditions # ----------------------------------------------------------------------- idb = zeros(ndf,nnp); idb[:,6].=1; idb[2,10]=1; # ---- BOUNDARY CONDITIONS: PRESCRIBED NODAL DISPLACEMENTS -------------- # g(i,N) = prescribed displacement magnitude # N = 1,...,nnp # i = 1,...,nsd # # 1) initialize g to 0 # 2) enter the values # ----------------------------------------------------------------------- g = zeros(ndf,nnp); # ---- BOUNDARY CONDITIONS: PRESCRIBED NODAL FORCES --------------------- # f(i,N) = prescribed force magnitude # N = 1,...,nnp # i = 1,...,nsd # # 1) initialize f to 0 # 2) enter the values # ----------------------------------------------------------------------- P = 20.0* 1000; # lbf f = zeros(ndf,nnp); f[2,7] = -P; f[2,8] = -P; f[2,9] = -P; return [A,E,f,g,idb,ien,ndf,nel,nen,nnp,nsd,xn] end # ======================================================================= function mapp(value, x1, y1, x2, y2) return (value - x1) * (y2 - x2) / (y1 - x1) + x2; end # ======================================================================= function plotTruss(problem,X,scale,threshold=0) nel=length(X) E,f,g,idb,ien,ndf,nel,nen,nnp,nsd,xn,len,Ke,Te=problem; K,F,d,stress,dcomp,g=FEM_truss(problem,X); p=plot(axis=nothing,ticks=nothing, border=nothing, aspect_ratio=:equal) for i in 1:nel if X[i]>threshold if threshold>0 p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(0.0,0.0,0.0), linewidth = 3.0) else p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(mapp(stress[i], minimum(stress[:]), maximum(stress[:]), 1, 0),0.0, mapp(stress[i], minimum(stress[:]), maximum(stress[:]), 0, 1)), linewidth = X[i]*scale) # linewidth = mapp(X[i], minimum(X[:]), maximum(X[:])+0.0001, scale/10.0, scale)) # p=annotate!((xn[1,Int(ien[1,i])]+xn[1,Int(ien[2,i])])/2.0, (xn[2,Int(ien[1,i])]+xn[2,Int(ien[2,i])])/2.0, "$(floor(stress[i]/1000))*e3", 8) end else p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(1.0,1.0,1.0), linewidth = 0.0) end end # plot!(axis=nothing,ticks=nothing, border=nothing) p end # ======================================================================= function getSetup(fileName) setup = Dict() open(fileName, "r") do f dicttxt = read(f,String) # file information to string setup=JSON.parse(dicttxt) # parse and transform data end return setup end # ======================================================================= function plotTrussDeformed(problem,X,scale,threshold=0,exageration=100.0) nel=length(X) E,f,g,idb,ien,ndf,nel,nen,nnp,nsd,xn,len,Ke,Te=problem; K,F,d,stress,dcomp,g=FEM_truss(problem,X); p=plot(axis=nothing,ticks=nothing, border=nothing, aspect_ratio=:equal) xnn=zeros(size(xn)) xnn.=xn .+ exageration.*dcomp for i in 1:nel if X[i]>threshold if threshold>0 p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(0.0,0.0,0.0), linewidth = 3.0) p=plot!([xnn[1,Int(ien[1,i])],xnn[1,Int(ien[2,i])]], [xnn[2,Int(ien[1,i])],xnn[2,Int(ien[2,i])]],label="", color=RGB(0.0,1.0,0.0), linewidth = 3.0) else p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(mapp(stress[i], minimum(stress[:]), maximum(stress[:]), 1, 0),0.0, mapp(stress[i], minimum(stress[:]), maximum(stress[:]), 0, 1)), linewidth = X[i]*scale) # linewidth = mapp(X[i], minimum(X[:]), maximum(X[:])+0.0001, scale/10.0, scale)) # p=annotate!((xn[1,Int(ien[1,i])]+xn[1,Int(ien[2,i])])/2.0, (xn[2,Int(ien[1,i])]+xn[2,Int(ien[2,i])])/2.0, "$(floor(stress[i]/1000))*e3", 8) end else p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(1.0,1.0,1.0), linewidth = 0.0) end end # plot!(axis=nothing,ticks=nothing, border=nothing) p end function plotTrussDeformed3D(problem,X,scale,threshold=0,exageration=100.0) nel=length(X) E,f,g,idb,ien,ndf,nel,nen,nnp,nsd,xn,len,Ke,Te=problem; K,F,d,stress,dcomp,g=FEM_truss(problem,X); p=plot(axis=nothing,ticks=nothing, border=nothing, aspect_ratio=:equal) xnn=zeros(size(xn)) xnn.=xn .+ exageration.*dcomp for i in 1:nel if X[i]>threshold if threshold>0 p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[3,Int(ien[1,i])],xn[3,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(0.0,0.0,0.0), linewidth = 3.0) p=plot!([xnn[1,Int(ien[1,i])],xnn[1,Int(ien[2,i])]], [xnn[3,Int(ien[1,i])],xnn[3,Int(ien[2,i])]], [xnn[2,Int(ien[1,i])],xnn[2,Int(ien[2,i])]],label="", color=RGB(0.0,1.0,0.0), linewidth = 3.0) else p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[3,Int(ien[1,i])],xn[3,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(mapp(stress[i], minimum(stress[:]), maximum(stress[:]), 1, 0),0.0, mapp(stress[i], minimum(stress[:]), maximum(stress[:]), 0, 1)), linewidth = X[i]*scale) # linewidth = mapp(X[i], minimum(X[:]), maximum(X[:])+0.0001, scale/10.0, scale)) # p=annotate!((xn[1,Int(ien[1,i])]+xn[1,Int(ien[2,i])])/2.0, (xn[2,Int(ien[1,i])]+xn[2,Int(ien[2,i])])/2.0, "$(floor(stress[i]/1000))*e3", 8) end else p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[3,Int(ien[1,i])],xn[3,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(1.0,1.0,1.0), linewidth = 0.0) end end # plot!(axis=nothing,ticks=nothing, border=nothing) p end function plotTruss3D(problem,X,scale,threshold=0) nel=length(X) E,f,g,idb,ien,ndf,nel,nen,nnp,nsd,xn,len,Ke,Te=problem; K,F,d,stress,dcomp,g=FEM_truss(problem,X); p=plot(axis=nothing,ticks=nothing, border=nothing, aspect_ratio=:equal) for i in 1:nel if X[i]>threshold if threshold>0 p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[3,Int(ien[1,i])],xn[3,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(0.0,0.0,0.0), linewidth = 3.0) else p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[3,Int(ien[1,i])],xn[3,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(mapp(stress[i], minimum(stress[:]), maximum(stress[:]), 1, 0),0.0, mapp(stress[i], minimum(stress[:]), maximum(stress[:]), 0, 1)), linewidth = X[i]*scale) # linewidth = mapp(X[i], minimum(X[:]), maximum(X[:])+0.0001, scale/10.0, scale)) # p=annotate!((xn[1,Int(ien[1,i])]+xn[1,Int(ien[2,i])])/2.0, (xn[2,Int(ien[1,i])]+xn[2,Int(ien[2,i])])/2.0, "$(floor(stress[i]/1000))*e3", 8) end else p=plot!([xn[1,Int(ien[1,i])],xn[1,Int(ien[2,i])]], [xn[3,Int(ien[1,i])],xn[3,Int(ien[2,i])]], [xn[2,Int(ien[1,i])],xn[2,Int(ien[2,i])]],label="", color=RGB(1.0,1.0,1.0), linewidth = 0.0) end end # plot!(axis=nothing,ticks=nothing, border=nothing) p end