Programming a Transient Truss Deflection Analysis

advertisement
Programming a Transient Truss Deflection Analysis
a project done during
Spring Quarter 2013-14
Ethan, Austin,
You've done a wonderful job on the program,
its validation, your presentation, and this report.
Thank you for a wonderful quarter,
L. O.
Project Grade:A
By
Ethan Cating
Austin Nash
May 23, 2014
In partial fulfillment of the requirements of the course
ME522
Advanced Finite Element Methods
Professor Lorraine G. Olson
Department of Mechanical Engineering
Rose-Hulman Institute of Technology
1
Table of Contents
Introduction, 3
Program Structure, 4
generating the input data, 4
elemental matrix assembly, 6
global matrix assembly, 8
forcing vector assembly, 10
constraint application, 12
solving the 2nd order system, 13
Program validation, 16
static case validation, 16
validation of forcing vector, 18
eigenvalue check and convergence check, 20
Creating and using the GUI, 23
Conclusions, 34
References, 35
Appendices, 36
2
Introduction:
In this project, a program was created to examine truss deflections. More specifically, a
transient simulation was performed to simulate the motion of a vehicle moving across a bridge.
Using assembly methods learned in this course and the previous course, global stiffness and
mass matrices were assembled along with a global forcing vector in order to calculate
deflections of a truss system as the vehicle was driven across the bridge. A transient analysis
was done using the trapezoidal method; at each step, a new forcing vector was created, and the
deflections were updated. In the end, it was possible to simulate the truss deflection pattern as
the vehicle moved across the bridge. A GUI was created to plot the simulation and to allow
users of the program to create their own truss design and see how it deformed during transient
loading. This report will detail the steps which were used in the programming and analysis;
validation of the model will also be discussed, and conclusions will be drawn about what was
learned from the project and what could be done in the future.
3
Program Structure:
In building the complicated program, an overall structure had to be obtained. A series of
Matlab functions were created in order to execute the overall routine needed to solve the
problem. Figure 1 shows a basic flow chart of the overall structure of the program.
Figure 1: Flow chart of the process in creating solution
Input data and formation of the truss shape:
As shown in the figure, the first phase of the overall program structure was to create the truss
shape using input data. There were a few components necessary. In order to illustrate the
formation of these inputs, a simple truss will be considered. This truss can be seen in Figure 2.
Figure 2: Simple bar/truss system
4
In Figure 2, blue numbers represent node numbers and red numbers represent element
numbers. The first input matrix is the coordinate matrix. This matrix has a row for each node,
with columns corresponding to the node number and the x and y positions of that node. For
this example, the coordinate matrix would be
[
]
(1)
The next input is the connectivity matrix. This matrix has a row for each element in the system,
with the first column containing the element number, followed by columns containing the
nodes which are connected by that element. For this example, the connectivity matrix is
[
]
(2)
Another input to the system is called the property matrix. In general, a property matrix has a
row for each element and columns depicting material properties of each element. For purposes
in this project, the Modulus of elasticity, cross-sectional area, and mass density were of concern.
Users can type desired material properties into the input function. Here, it is assumed that all
elements have the same properties. Thus, for the example in Figure 2, the property matrix is
1 E
2 E

A 
A  
(3)
The number of degrees of freedom was another input. For this project, there are two degrees of
freedom for each node: vertical deflection and horizontal deflection. This is due to the need of
putting all deflections back into a global coordinate system, which will be discussed later. The
final input to the system is the constraint matrix. It contains a row for each degree of freedom
being constrained. The first column is the node being constrained, the second column is the
degree of freedom constrained for that node (1 for x, 2 for y), and the third column is the
5
constrained displacement, which is always zero for this project. For the current example, the
constraint matrix for fixing the first node is
[
]
(4)
The Matlab function containing the input data for this project is called func_input_data and can
be found in Appendix A.
NOTE: Users of the program can type their nodal data into this function by hand and simulate
the deflections with the plotting GUI. Alternatively, they can use the drawing GUI which
allows users to point and click on a grid of points and draw their own truss. In this case, the
drawing GUI is set up such that it sends the nodal coordinates and element connections into
this input function. Then, the data can be simulated and plotted as usual.
Assembly of elemental matrices:
Looking back at Figure 1, the next step was to create the elemental mass and stiffness matrices
for each of the elements in the system. In local coordinates of a particular element, the
elemental mass and stiffness matrices are given by (5) and (6)
[
[
]
(5)
]
(6)
However, the elemental mass and stiffness matrices must be rotated into a global frame to
account for rotated elements; this is because the truss elements can only deform in the
longitudinal direction. Thus, it is necessary to resolve the local coordinate deflections of rotated
elements into global u and v coordinates. Figure 3 shows a truss element rotated at angle α and
(7) shows the matrix needed for transforming the deflection from local to global coordinates.
6
Figure 3: Rotated element
[
cos 
0
sin 
0
0
cos 
0
]
sin 
(7)
Applying the rotation transformation, the final equations for the elemental stiffness and mass
matrices are given by (8) and (9).
(8)
(9)
The Matlab function used in this project to create the element stiffness and mass matrices is
called func_2D_truss_element and can be found in Appendix B. A brief overview of the function
is depicted below in Figure 4.
7
Figure 4: Basic structure of elemental assembly Matlab function
As seen in Figure 4, the elemental mass and stiffness matrices are assembled via a loop over all
elements in the top level of the code. The top level sends to the function the nodes of an
element and their coordinates along with the element’s properties. The function then calculates
the angle of the element and the length of the element and assembles the proper elemental
matrices, which are then sent back to the top level and stored in a 3D array.
Global matrix assembly:
Next, the global mass and stiffness matrices must be formed. This was done via a direct
assembly method. For example, in the simple example from Figure 2, global assembly of the
stiffness matrix would give
1
0 1 0
0 0
1 0
0 0
0
[ 0
0
2
0
0
0 0 0
0 1 0
0 0 0
0 1 0
0 0 0
8
0
1
0
0
0]
(10)
Here, the overlap occurs for the rows and columns associated with the degrees of freedom of
node two due to the fact that node two connects the two elements. The global mass matrix is
assembled in a similar manner.
The Matlab function used in this project to create the global mass and stiffness matrices is called
func_direct_assembly and can be found in Appendix C. A brief overview of the function is
depicted in Figure 5.
Figure 5: Basic structure of direct (global) assembly Matlab function
As seen in Figure 5, the top level calls the global assembly function and sends in the
connectivity data and the collection of elemental mass and stiffness matrices, as well as the total
number of nodes and elements in the system. Inside the function, there is a loop over all of the
elements. For the current element, the function uses the connectivity matrix and the number of
DOFs to determine which DOFs are associated with that element. Then, the elemental matrices
are added into the proper rows and columns of the global matrices. After each element is
added into the global matrices, they are then sent back to the top level of the code.
9
Forcing vector assembly:
In order to create the load vector, it was assumed that the only two forces acting on the truss
system were point loads associated with each wheel set: the front wheels and the back wheels.
It was assumed that half of the vehicle’s weight acted on the truss as a point load at the point of
contact with the rear wheels and the other half of the vehicle’s weight acted on the truss as a
point load at the point of contact with the front wheels. In instances where a wheel set was on a
node, that node’s vertical DOF received the entire wheel set’s force. However, in instances in
which the wheel(s) were located between the nodes of an element, the point loads of the wheels
had to be resolved into nodal loads acting on each node of the element. An example of the
proper way to split the point load into nodal loading is depicted below in Figure 6 and (11).
Figure 6: Schematic for splitting force into nodal forces
If the wheel in question is on an element but between its two nodes, the forces are split. This is
done using the shape functions. Here, it can be said that
. Now, the nodal forces are
given by
{ }
( )
{
}
{
10
}
{ }
(11)
The Matlab function used in this project to create the global load vector is called myloadvec2 and
can be found in Appendix D. A brief overview of the function is depicted below in Figure 7.
Figure 7: Flow chart for executing load vector formation
Inputs sent into the function are the connectivity and coordinate matrices, as well as the car
length and weight and the x-position of the center of the car (d). The locations of the wheel
forces are found using the car length and d. In the function, there is a loop over each element.
Inside the loop, there are stacked if-statements for each of the point loads due to the wheel sets’
forces (two point loads total). The code determines whether either wheel is on the current
element. If it is not, the code simply goes on to the next element. If it is, the code then
determines where the wheel is on the element. If it is in between the nodes, the force is split
accordingly. If it is on the left node, the code then determines if the left node is the leftmost
point of the truss system, in which case the node gets all of the force. If the node is the left node
of an internal element, it gets only half of the load because it will then get the other half when
11
the next element is sent through the if-statements. The same logic applies when the wheel is on
the right node of an element. If that right node is the rightmost point of the system, the whole
force is given to that node. If not, only half of the force is given. It is worth noting that all loads
are given to the load vector entry corresponding to the vertical DOF of each node.
Constraint application using elimination:
The final step before solving for displacements was to constrain the system. It is worth noting
that Allaire’s method was used initially. However, it failed to work for truss systems which
were completely horizontal or vertical due to matrix singularity. Using elimination fixes this
because the rows and columns of zeroes can be eliminated. Elimination is done by simply
striking out the rows and columns in the global mass and stiffness matrices and forcing vector
which are associated with a constrained degree of freedom. For our simple case from Figure 2,
the first two DOFs are constrained. Thus, these would be eliminated from the global matrices.
The constrained stiffness matrix is now given by
1
0 1 0
0 0
1 0
0 0
0
[ 0
0
2
0
0
0
0 0 0
0 1 0
0 0 0
0 1 0
0 0 0
1
0
0
0]
2
0
1
[ 0
0 1
0 0
0 1
0 0
0
0
0
0]
(12)
The mass matrix and forcing vector are similarly constrained. By applying constraints, systems
become non-singular, and deflections can be solved for.
(NOTE: In order to solve a system with this particular stiffness matrix, one would have to
eliminate rows and columns two and four. This can be done by telling the program that each
node is on a roller constraining it in the vertical direction. This simple example was only being
used to illustrate the process.)
12
The Matlab function used in this project to apply constraints is called elimination and can be
found in Appendix E. A brief overview of the function is depicted below in Figure 8.
Figure 8: Flow chart for application of constraints to the system matrices
As seen in Figure 8, there is a loop over the constraint matrix in the function. The function
reads in the nodes which are constrained and which DOFs of that node are constrained. It then
removes the rows and columns associated with that DOF from the mass and stiffness matrices
as well as the entry of the load vector associated with that DOF. The function also stores the
constrained DOFs into an array so that the proper zero deflections can be added back into their
proper places in the displacement vector after solving for the non-constrained displacements.
Solving the system via 2nd order trapezoidal method:
The transient equation for this system is given by
̈ +Ku = F
13
(13)
In this project, the trapezoidal method was used to solve for the transient displacement at each
time step. Using the trapezoidal method to solve the equation is beneficial due to the fact that
this method is unconditionally stable. Thus, the time step is not as crucial as it would be for
other methods. The complete set of equations used in solving the transient problem can be
found in the course textbook in section 5.6.2 [1]; a copy of the page can also be found in
Appendix G.
A basic overview of this method is depicted below in Figure 9.
Figure 9: Overview of trapezoidal method for solving transient equation
Intermediate variables Khat and Fhat are created. These are used to solve for the deflections at the
next time step. Then, the velocity and accelerations are updated. The total displacement vector
at the next time step is then created by adding in zeroes for the constrained DOFs.
Once the deflections were found, the car moved to a new position given by
(14)
14
In (14), d represents the x-position of the center of the car, V represents the car velocity, for
which 15 m/s was used, and
represents the time step, for which 0.001 seconds was used.
With a new car position, the forcing vector is then updated, constraints are reapplied, and new
deflections are found. This process is repeated iteratively until the rear wheel of the vehicle
reaches the end of the bridge.
15
Program Validation:
In order to validate the program, many test cases were run. In each case, the program created
for this project was used to obtain an answer which was then checked with a theoretical answer
derived from class or from a textbook. Each case is presented below.
Static case from course text:
The first test case was a simple static truss problem from the course notes [1]. There is a
horizontal bar connected to a vertical bar, with each bar constrained at one node. The nonconstrained node is pulled on in the vertical direction. The purpose of using this test case was
to determine that the elemental and global matrix assembly functions and the constraint
function were all working properly. A schematic of the test case is seen in Figure 10.
Figure 10: Schematic for splitting force into nodal forces
In Figure 10, the elemental stiffness matrices are given by
0 0
0 1
0 0
[ 0 1
16
0 0
0 1
0 0
0 1 ]
(15)
0 1
0 0
0 1
0 0
1
0
1
[ 0
0
0
0
0]
Assembling the global system gives
0
0
0
0
0
[0
0
0
0
0
0
u1
1 0  1 0 0 v1
0 1 0 1 0 u2
1 0 1 0 0 v2
0 1 0 1 0 u3
0 0 0 0 0 ] { v3 }
0
0
 
 0 
 
F 
0
 
 0 
(16)
Applying constraints, the system becomes
[
This implies that
and
]{
}
{ }
(17)
.
Using the program created for this project and setting F,L,E, and A all equal to unity, the
displacement vector was calculated to be
{0 0 0 1 0 0}
(18)
, signaling that the program succeeded in passing the static deflection test case. The success of
this case signaled that the stiffness matrix formation and assembly was working correctly as
well as the constraint application.
17
Validation of the forcing vector assembly:
It was necessary to make sure that the forcing vector function was correctly finding the global
forcing vector. In order to do this, a few test cases were determined. It was necessary to make
sure that the forcing vector was handling situations where the wheels were on the nodes of an
element and between the nodes of an element. Four test cases were applied; schematics can be
seen below in Figure 11.
Figure 11: Test cases used for forcing vector validation
In Case 1, one would expect the global forcing vector to return a force equal to the wheel force
for the y-degree of freedom associated with node one (the leftmost node). This case was used
because it was necessary to see that the whole load was given to that DOF. With a car weight of
10,000 N (wheel forces of -5,000 N), the program returned
{ 0  5000 0 0 0 0 0 0 }
18
(19)
This is a very small point, but I
thought I would mention it for your
future writing. The comma goes
with the equation, not on the
following line.
, which signaled a success. For Case 2, the program returned
{ 0 0 0 0 0 0 0  5000 }
(20)
, again signaling a success. Case 3 was used in order to determine that the looping through
elements didn’t cause too much force to be added to a node. For example, if the whole wheel
force was applied when the wheel was on an internal node, it would get doubled when the loop
moved onto the next element. For Case 3, the program returned a forcing vector which was
{ 0 0 0  5000 0  5000 0 0 }
(21)
, which is the proper forcing vector. Case 4 was used to ensure that the forces were split
properly in cases where the wheels were applying forces between the two nodes of an element.
For the first wheel, the proper split is given by
{
}
( )
{
}
{
}
(22)
}
{
}
(23)
For the second wheel, the proper split is given by
{
}
( )
{
Using assembly for Case 4, this would give a forcing vector of
19
F1 y
F2 y
F3 y
{ F4 y }
{ 0.2 1 0.8 0 }
(24)
The program returned a forcing vector of
{ 0  1000 0  5000 0  4000 0 0 }
(25)
, which is the correct forcing vector for a 10,000 N car assuming the geometry of Case 4. The
load vector seemed to pass all conditions that it could encounter for the vehicle problem. Thus,
it was deemed that the load vector was being assembled properly.
Eigenvalue check and convergence check:
The last checks were to check convergence and to check that the eigenvalues produced by the
constrained system were in accordance with tabulated values of natural frequencies for
longitudinally vibrating beams [2]. In order to check convergence, a simple horizontal bar was
fixed at one end and pulled on at the other end, as in Figure 12.
Figure 12: Simple bar/truss system to check for convergence
The idea was to take the bar and find the corresponding eigenvalues and compare them to the
theoretical eigenvalues. This would ensure that the mass and stiffness matrices were correctly
20
assembled and constrained. This check would all but ensure the program to be working
seamlessly.
In theory, the natural frequencies of the bar are given by reference
(
√
Using E = 200 GPa and
)
(26)
= 8000 kg-m-3, the first three theoretical natural frequencies were found
to be
{ }
{
}
(27)
Using the program developed in this project, for a bar split into 5 elements and 6 nodes, it was
found that
{ }
{
}
(28)
Using the program developed in this project, the number of elements and nodes was then
increased to check that the values did not significantly change. For a bar split into 15 elements
and 16 nodes, it was found that
{ }
{
}
(29)
The values were extremely close to the theoretical values, again signaling that the program was
working correctly. Additionally, the values returned from the program for each mesh were
21
really close to each other, signaling that our mesh was experiencing convergence and that
nothing out of the ordinary was happening when the mesh was refined.
Using the same two configurations, the tip deflection of the rod was also found and compared
to the theoretical value. The theoretical value is given by
presumably this is a static tip
deflection
(30)
Using each of the meshes tested above, the tip deflections were found to be 0.0023 m, matching
the expected value. This was just another simple check to make sure that there were no issues
with refining the mesh and obtaining convergence.
This concluded the tests performed on the program. Through testing, the program was deemed
to be working correctly to the best of the testers’ knowledge. Each part of the Matlab program
was tested for validation, and each passed the test.
22
Creating the GUI: Allowing simulation of motion and user defined GUI
Truss Program Animation and Drawing GUI
The final aspect of the project was to create a graphical user interface (GUI) that lets the user
create and animate a truss design. This section outlines the steps to using the GUI successfully.
The code for the two GUI’s, Truss_Program_GUI and Truss_Drawing_GUI, are located in
Appendix H and I, respectively.
The main GUI, Truss_Program_GUI, is shown in the following form during an animation (see
Figure 13). This is what the user sees while the simulation of motion is occurring.
Figure 13: Truss_Program_GUI during transient deflection animation
Figure 14 is a picture of the drawing GUI, Truss_Drawing_GUI, during node placement and
element creation. It is a sub-function of the main GUI. The image is a representation of the
process of creating a truss.
23
Figure 14: Truss_Drawing_GUI during element creation state
The user interface is a rough design, with much more work that would need to be done before
mass distribution. The steps to go through the process of using the GUI are straightforward, but
do not allow for much use outside of those steps. Any use of the GUI that strays from what was
intended will most likely lead to errors and the program not working.
Once the program is run for the first time, the initial screen is as shown below in Figure 15.
24
Figure 15: Truss_Program_GUI after just starting the program
From this point, there are three selectable items for the user to choose from and a message box
at the top right hand corner telling the user what file they have selected if they chose to load
truss data. For this example it is easier to show how to create a new truss design, load that data,
and then animate it. The user also has the option to load any set of nodes and elements already
created to simulate and animate at any time rather than creating a new design before loading.
The Create New Bridge option will be used in this example as shown in Figure 16.
Figure 16: Truss_Program_GUI select menu
25
After selecting that option in the select menu, a prompt asks the user for the name of the bridge
design they are creating. In this example, the data is saved as Example_Case. Click the save
button to move on as shown in Figure 17.
Figure 17: Truss_Drawing_GUI save new truss dialog box
Once the name of the bridge design is saved as its own .mat file, all of the bridge design data
will be saved to that .mat file. Also once it is saved, the drawing GUI appears over the main
GUI. It contains another select menu, two radio buttons, a save button, a message box, and a
reset button. (The reset button is still not finished. Most of the code is there, but there are a few
problems with it. If the user needs to erase points or start over, it is best to just close the
drawing GUI and restart from the main GUI.) The select menu has the options for which bridge
size the user would like to use for their bridge design, as seen in Figure 18. Short will be used in
this example.
26
Figures 18: Truss_Drawing_GUI while loading bridge design
Once the bridge size is selected, the select menu is disabled so that the loop for saving the nodes
and elements does not have a problem saving the data and sending it to the input function
described earlier in the report. The user must then click on the Nodes radio button as depicted
in Figure 19. A set of cross hairs will appear for the user to select the points they want their
nodes to be located at and selections snap to the closest grid point on the screen. This phase
continues until the user presses the E button on the keyboard to exit node selection.
27
Figure 19: Truss_Drawing_GUI during node selection state
Once the E button is pressed, the cross hairs go away. The message box lets the user know that
they have left the node selection option, and the Nodes radio button is unchecked. The nodes
remain on screen for the remainder of use of the drawing GUI as seen in Figure 20.
28
Figure 20: Truss_Drawing_GUI with nodes in place
The user then selects the Elements radio button as depicted in Figure 21 and is able to draw
lines that connect the nodes to each other. The crosshairs reappear and selections snap to the
closest node within a small distance. The function only allows for nodes to be selected so that
users cannot create elements with no nodal endpoints. Additionally, the message has changed
to show that the user is in element selection mode. The way to exit this mode is by pressing the
R button on the keyboard twice.
29
Figure 21: Truss_Drawing_GUI during element creation state
Once the user has finished placing all the elements they would like for their design and have
pressed the R button twice, the user has exited element creation mode. The message box shows
this and the Elements radio button is unchecked. The save button is now enabled as in Figure 22
and once clicked, it saves the bridge node and element data to the .mat file and closes the
drawing GUI.
30
Figure 22: Saving a finished truss design
The user is then returned to the main GUI depicted in Figure 23 on the following page. Now
one must load the input data of the newly created bridge. Using the option of loading the
bridge in the select menu, the bridge data is loaded for use in the program. The name of the
loaded .mat file is now in the message box.
31
Figure 23: Loading a saved bridge design
After selecting the Load Bridge option, the user selects the bridge from the folder they saved it
to and it loads in, as in Figure 24.
Figure 24: Selection of proper truss input file
32
Once the coordinate and connectivity data is loaded, it needs to be simulated to get the
deflection data. Press the Simulate button to solve for the deflection data. Doing this causes the
top level script Simple_FEA_Program to run, which solves for deflections at each time step. That
data is then appended to the .mat file. Once this is complete the user can press the Animate
button as depicted in Figure 25 and watch the fruits of their labor. For the case of bridge data
already made, the user can just hit the animate button once they load the data.
Figure 25: Truss_Program_GUI animating truss deflection as the car moves
This completes the process of creating a truss design and simulating its subsequent deflections
as a vehicle is driven across its elements.
This also concludes the content of the program created in this project. There are two phases:
the input data is created and gathered/saved, and the deflections are then calculated via the
functions described in this report. The motion is then plotted using the GUI developed above.
33
Conclusions:
In doing this project, we found that creating a complex code takes many steps and phases. For
example, there were many functions used in the program. It was necessary to examine each
function individually in order to ensure that each was working properly.
There are several areas of this project that could use additional study and work. For example, it
would be nice to do some post-processing on the deflection data. Using the nodal deflections,
we could then take the element cross-sectional areas and calculate the stress in each element at
each time step. These stresses could then be displayed on the GUI as the car drives across the
bridge. This could be useful for a fun example in an EM121 course.
Another possibility for improvement would be to perform additional work to incorporate other
forces into the model. Currently, the only forces in the system are point forces associated with
the wheels. Other forces could be added into the analysis, such as horizontal friction forces due
to the wheels contacting the trusses. Another option could be to consider the weight of the
beams.
An area for future work on the GUI could be to use a point-and-click method which will display
nodes and elements at the same time, rather than in separate processes. Adding error codes
into the GUI would be nice, as well. This could be beneficial so that users would know why a
design fails.
Overall, we feel that the project was a success. It was a good learning experience in creating a
rather complex analysis by combining several simple ideas. We feel that this project could be
beneficial to us later on in our careers. We will most likely encounter problems such as this one,
where an immediate solution is not apparent and one must create complex programs that work
together to develop a finished product.
We would also like to thank Dr. Jones for allowing us to use and amend some of his global
assembly code from the ME422 course [3]. It was a great help to us in this project.
34
References:
[1] L. G. Olson, Advanced Finite Element Methods, Terre Haute, IN: Rose-Hulman Institute of
Technology, 2014.
[2] R. D. Blevins, Formulas for Natural Frequency and Mode Shape, New York, NY: Van
Nostrand Reinhold Company, 1979.
[3] S. Jones, Finite Element Analysis, Terre Haute, IN: Rose-Hulman Institute of Technology,
2013-14.
35
Appendix A: func_input_data (Input data function)
function [CoordMat,ConnMat,PropMat,nDOF,ConstrMat]=func_input_data
rho = 8000; E = 200e9;
A
= 3250/(1000^2);
% Coordinate Matrix lists the position of each node
% format: node number, x position, y position [m]
CoordMat = sortrows([...
1 0 0;
2 5 0;
3 10 0;
4 15 0;
5 12.5 8;
6 7.5 8;
7 2.5 8;]);
% Connectivity Matrix details which nodes are in each element
% format: element number, node 1, node 2
ConnMat = [...
1 1 7;
2 1 2;
3 2 7;
4 6 7;
5 2 6;
6 2 3;
7 3 6;
8 5 6;
9 3 5;
10 3 4;
11 4 5];
% Property Matrix lists the properties for each element
% format: element number, elastic modulus [Pa], cross-sectional area [m^2]
PropMat = zeros(size(ConnMat,1),4);
PropMat(1:size(ConnMat,1),1) = [1:1:size(ConnMat,1)];
PropMat(1:size(ConnMat,1),2) = E;
PropMat(1:size(ConnMat,1),3) = A;
PropMat(1:size(ConnMat,1),4) = rho;
% Number of degrees of freedom for each node
nDOF = 2;
% Constraint Matrix lists the constraints on particular nodes
% format: node number, direction (x=1, y=2), prescribed displacement
ConstrMat = [...
1 1 0;
1 2 0;
4 1 0;
4 2 0];
36
Appendix B: func_2D_truss_element (elemental matrix assembly function)
function [ke, me] = func_2D_truss_element(numElem,CoordMat,ConnMat,PropMat)
% read in the properties for the current element
E = PropMat(numElem,2);
A = PropMat(numElem,3);
rho = PropMat(numElem,4);
% pick out the 2 nodes contained in this element
node1 = ConnMat(numElem,2);
node2 = ConnMat(numElem,3);
% find the position of each node
x1
y1
x2
y2
=
=
=
=
CoordMat(node1,2);
CoordMat(node1,3);
CoordMat(node2,2);
CoordMat(node2,3);
% compute the element length (ell) and the inclination angle (theta)
ell = sqrt((x2-x1)^2 + (y2-y1)^2);
theta = atan((y2-y1)/(x2-x1));
% shorthand notation for cosine and sine
c = cos(theta);
s = sin(theta);
% compile the element stiffness matrix
ke = E*A/ell*[...
c^2, c*s, -c^2, -c*s;
c*s, s^2, -c*s, -s^2;
-c^2, -c*s, c^2, c*s;
-c*s, -s^2, c*s, s^2];
T = [cos(theta),sin(theta),0,0;0,0,cos(theta),sin(theta)];
M = rho*A*ell/6*[2,1;1,2];
me = T'*M*T;
end
37
Appendix C: func_direct_assembly (global matrix assembly function)
function [K,M] = func_direct_assembly(nDOF,numNode,numElem,ConnMat,Ke,Me)
% predefine the size of the global stiffness matrix
K = zeros(nDOF*numNode,nDOF*numNode);
M = zeros(nDOF*numNode,nDOF*numNode);
% use the direct assembly method to compile the global stiffness matrix
for II = 1:numElem
n1 = ConnMat(II,2);
n2 = ConnMat(II,3);
% node 1
% node 2
n1_dofs = (2*(n1-1)+(1:2));
n2_dofs = (2*(n2-1)+(1:2));
% dofs associated with node 1
% dofs associated with node 2
K(n1_dofs,n1_dofs)
K(n1_dofs,n2_dofs)
K(n2_dofs,n1_dofs)
K(n2_dofs,n2_dofs)
=
=
=
=
K(n1_dofs,n1_dofs)
K(n1_dofs,n2_dofs)
K(n2_dofs,n1_dofs)
K(n2_dofs,n2_dofs)
+
+
+
+
Ke(1:2,1:2,II);
Ke(1:2,3:4,II);
Ke(3:4,1:2,II);
Ke(3:4,3:4,II);
M(n1_dofs,n1_dofs)
M(n1_dofs,n2_dofs)
M(n2_dofs,n1_dofs)
M(n2_dofs,n2_dofs)
=
=
=
=
M(n1_dofs,n1_dofs)
M(n1_dofs,n2_dofs)
M(n2_dofs,n1_dofs)
M(n2_dofs,n2_dofs)
+
+
+
+
Me(1:2,1:2,II);
Me(1:2,3:4,II);
Me(3:4,1:2,II);
Me(3:4,3:4,II);
end
38
Appendix D: myloadvec2 (load vector assembly function)
function [F] = myloadvec2(CoordMat,ConnMat,nDOF,d,Wc,Lc)
% d1 is the rear wheelset and d2 is the front wheelset
F1 = Wc/2;
F2 = Wc/2;
d1 = d - Lc/2;
F = zeros(size(CoordMat,1)*nDOF,1);
CoordMat = sortrows(CoordMat);
for i = 1:size(ConnMat,1)
d2 = d + Lc/2;
% initialize the load vector
% loop through elements
node1 = ConnMat(i,2); node2 = ConnMat(i,3);
% nodes for the elements
if CoordMat(node1,3) == 0 & CoordMat(node2,3) == 0
a ground element?
% is current element
x1 = CoordMat(node1,2); x2 = CoordMat(node2,2);
% element x
coords.
% make sure that we get the left/right nodes correctly
% interpreted
if x1 < x2
left_node = x1; right_node = x2;
else
left_node = x2; right_node = x1; node1 = ConnMat(i,3); node2
= ConnMat(i,2);
end
L = right_node - left_node;
% element length
% if-else statement for both wheels --- start with rear wheel
if d1 > left_node & d1 < right_node
% wheel between the two
nodes?
F(node1*nDOF) = F(node1*nDOF) + F1/L*(right_node - d1);
F(node2*nDOF) = F(node2*nDOF) + F1 - F1/L*(right_node - d1);
elseif d1 == left_node
% wheel on the first node?
if left_node == min(CoordMat(:,2))
F(node1*nDOF) = F(node1*nDOF) + F1;
else
F(node1*nDOF) = F(node1*nDOF) + F1/2;
end
elseif d1 == right_node
% wheel on the second node?
if right_node == max(CoordMat(:,2))
F(node2*nDOF) = F(node2*nDOF) + F1;
else
% if here, wheel isn't on current element
F(node2*nDOF) = F(node2*nDOF) + F1/2;
39
end
else
F(node1*nDOF) = F(node1*nDOF) + 0;
F(node2*nDOF) = F(node2*nDOF) + 0;
end
% repeat for the other wheel
if d2 > left_node & d2 < right_node
F(node1*nDOF) = F(node1*nDOF) + F2/L*(right_node - d2);
F(node2*nDOF) = F(node2*nDOF) + F2 - F2/L*(right_node - d2);
elseif d2 == left_node
if left_node == min(CoordMat(:,2))
F(node1*nDOF) = F(node1*nDOF) + F2;
else
F(node1*nDOF) = F(node1*nDOF) + F2/2;
end
elseif d2 == right_node
if right_node == max(CoordMat(:,2))
F(node2*nDOF) = F(node2*nDOF) + F2;
else
F(node2*nDOF) = F(node2*nDOF) + F2/2;
end
else
F(node1*nDOF) = F(node1*nDOF) + 0;
F(node2*nDOF) = F(node2*nDOF) + 0;
end
else
F(node1*nDOF) = F(node1*nDOF) + 0;
F(node2*nDOF) = F(node2*nDOF) + 0;
end
end
end
40
Appendix E: elimination (constraint application function)
function [K_c,M_c,F_c,cdof] = elimination(K,M,F,ConstrMat)
% loop through each constraint
for k = 1:size(ConstrMat,1)
% decide which dof the matrix is telling us to constrain --% i.e. - is it constraining an x-dir dof or a y-dir dof?
if rem(ConstrMat(k,2),2) == 0
cdof(k) = ConstrMat(k,1)*ConstrMat(k,2);
else
cdof(k) = 2*ConstrMat(k,1)*ConstrMat(k,2)-1;
end
end
% apply elimination method to the mass and stiffness matrices and the
% load vector
K(cdof,:)=[];
K(:,cdof) = [];
M(cdof,:)=[];
M(:,cdof) = [];
F(cdof) = [];
K_c = K;
M_c = M;
F_c = F;
end
41
Appendix F: Simple_FEA_Program (top level code calling all functions)
%Simple_FEA_program
clear all
close all
clc
% grab the input data
[CoordMat,ConnMat,PropMat,nDOF,ConstrMat]=func_input_data;
numElem = size(ConnMat,1);
numNode = size(CoordMat,1);
% create the element matrices (do for each element)
for II = 1:numElem
[ke, me] = func_2D_truss_element(II,CoordMat,ConnMat,PropMat);
Ke(:,:,II) = ke;
clear ke
Me(:,:,II) = me;
clear me
end
% global assembly --- direct assembly method
[K,M] = func_direct_assembly(nDOF,numNode,numElem,ConnMat,Ke,Me);
% initialize car location; get ready for time stepping
Lc = 4;
d = -Lc/2;
dtot(1) = d;
Wc = -10000;
i = 1; u = zeros(numNode*nDOF-size(ConstrMat,1),1); ud = u; udd = u;
time(i) = 0;
dt = 0.001;
V = 15;
% transient loop for driving car;
% forcing vector
each time, get new values for the
while d - Lc/2 <= max(CoordMat(:,2))
[f] = load_vector_v2(CoordMat,ConnMat,nDOF,d,Wc,Lc);
[K_c,M_c,F_c,cdof] = elimination(K,M,f,ConstrMat);
K_hat = K_c + 4/(dt^2)*M_c;
F_hat = F_c + M_c*(4/(dt^2)*u(:,i) + 4/dt*ud + udd(:,i));
u(:,i+1) = K_hat\F_hat;
ncdof = [1:nDOF*numNode];
ut(cdof,i+1) = 0;
ncdof(cdof) = [];
ut(ncdof,i+1) = u(:,i+1);
42
udd(:,i+1) = 4/(dt^2)*(u(:,i+1)-u(:,i)) - 4/dt*ud - udd(:,i);
ud = ud + dt/2*udd(:,i) + dt/2*udd(:,i+1);
time(i+1) = time(i) + dt;
dtot(i+1) = d + V*dt;
i = i + 1;
d = d + V*dt;
end
% store the new nodal positions at each time step
for i = 1:size(ut,2)
utot(1:numNode,i) = ut(1:2:numNode*nDOF-1,i) + CoordMat(:,2);
vtot(1:numNode,i) = ut(2:2:numNode*nDOF,i) + CoordMat(:,3);
end
save('Simple_Truss.mat', 'CoordMat', 'ConnMat', 'utot', 'vtot', 'numNode',...
'nDOF', 'ut', 'dtot','Lc')
43
Appendix G: Trapezoidal Method from Course Notes
44
Appendix H: Truss_Program_GUI (main GUI function)
function Truss_Program_GUI
% Truss_Program_GUI animates the deflection
% Create and hide the GUI as it is being constructed.
f = figure('Visible','on','Position',[320,120,1280,800],'Resize','off');
set(gcf,'Color','w')
set(f,'Name','Truss Deflection Simulation and Animation')
% Construct the components
hanim = uicontrol('Style','pushbutton','String','Animate',...
'Position',[1050,30,200,100],'Callback',{@hanim_Callback});
hsim = uicontrol('Style','pushbutton','String','Simulate',...
'Position',[1050,150,200,100],'Callback',{@hsim_Callback});
hselect = uicontrol('Style','popupmenu','String',{'....','Load
Bridge','Create New Bridge'},...
'Position',[1060,650,180,50],'Callback',{@hselect_Callback});
hpanel = uipanel(f,'Units','pixels','Position',[30,30,1000,748],...
'Title','Animation','BackgroundColor','w');
hpanel2 = uipanel(f,'Units','pixels','Position',[1050,728,200,50],...
'Title','Bridge Selected','BackgroundColor','w');
hpanel3 = uipanel(f,'Units','pixels','Position',[1050,668,200,50],...
'Title','Load or Create','BackgroundColor','w');
ha = axes('Units','pixels','Position',[35,35,990,740],...
'Visible','off','HandleVisibility','callback');
htext = uicontrol('Style','text','String','- - - - - - - - - - - - - - - - -',...
'Position',[1060,738,180,20],'BackgroundColor','w');
% Function Callbacks
function hanim_Callback(source,eventdata)
% Animates the deflection data
% Load in Saved Data from Simple_FEA_program
fn = guidata(f);
Data = load(fn);
CoordMat = Data.CoordMat;
ConnMat = Data.ConnMat;
utot = Data.utot;
vtot = Data.vtot;
numNode = Data.numNode;
45
nDOF = Data.nDOF;
ut = Data.ut;
sf = .25/max([max(max(ut)) abs(min(min(ut)))]);
dtot = Data.dtot;
Lc = Data.Lc;
xbase = Data.xbase;
% Find the largest deflection in the system
for i = 1:size(ut,2)
for l = 1:length(ConnMat)
diffu1 = (utot(ConnMat(l,2),i)-utot(ConnMat(l,2),1));
diffu2 = (utot(ConnMat(l,3),i)-utot(ConnMat(l,3),1));
diffv1 = (vtot(ConnMat(l,2),i)-vtot(ConnMat(l,2),1));
diffv2 = (vtot(ConnMat(l,3),i)-vtot(ConnMat(l,3),1));
diffu = abs(diffu2-diffu1);
diffv = abs(diffv2-diffv1);
max_diff_frac = sqrt(diffu^2 + diffv^2);
frac(i) = max_diff_frac;
end
end
col_frac = frac(:)./max(frac(:));
% Plot transient deflections
for i = 1:size(ut,2)
dutot(1:numNode,i) = ut(1:2:numNode*nDOF-1,i).*sf;
dvtot(1:numNode,i) = ut(2:2:numNode*nDOF,i).*sf;
utot(1:numNode,i) = dutot(1:numNode,i) + CoordMat(:,2);
vtot(1:numNode,i) = dvtot(1:numNode,i) + CoordMat(:,3);
aa = xbase(end) + 2; bb = max(CoordMat(:,3))*7/4;
axis([-2 aa -2 bb])
box off
set(gcf,'Color','w')
hold on
% draw and plot moving car
ct = rectangle('Position',[dtot(i)1.75,0.75,3,1.5],'Curvature',[1,0.875],...
'FaceColor','r');
cw = rectangle('Position',[dtot(i)1.625,0.875,2.75,1.25],'Curvature',[1,0.875],...
'FaceColor','w');
cp = rectangle('Position',[dtot(i).375,0.75,.25,1.375],'FaceColor','r');
cb = rectangle('Position',[dtot(i)-1Lc/2,0.5,6,1],'Curvature',[0.8,0.4],...
'FaceColor','r');
dft = rectangle('Position',[dtot(i)0.5+Lc/2,0,1,1],'Curvature',[1,1],...
'FaceColor','k');
drt = rectangle('Position',[dtot(i)-0.5Lc/2,0,1,1],'Curvature',[1,1],...
'FaceColor','k');
46
dfw = rectangle('Position',[dtot(i)0.375+Lc/2,0.125,0.75,0.75],'Curvature',[1,1],...
'FaceColor','w');
drw = rectangle('Position',[dtot(i)-0.375Lc/2,0.125,0.75,0.75],'Curvature',[1,1],...
'FaceColor','w');
% plot truss lines
for l = 1:length(ConnMat)
inline(l) = line([utot(ConnMat(l,2),1) utot(ConnMat(l,3),1)],...
[vtot(ConnMat(l,2),1) vtot(ConnMat(l,3),1)],...
'LineStyle','--','LineWidth',0.1,'Color','k');
hline(l) = line([utot(ConnMat(l,2),i) utot(ConnMat(l,3),i)],...
[vtot(ConnMat(l,2),i) vtot(ConnMat(l,3),i)],...
'Color',[col_frac(i) 0 1-col_frac(i)],'LineWidth',5);
end
% plot water and road entras and exits
rectangle('Position',[0,-2,aa-2,1],'FaceColor','c','EdgeColor','c')
rectangle('Position',[-2,-2,2,2],'FaceColor','k')
rectangle('Position',[aa-2,-2,2,2],'FaceColor','k')
a_orig = plot([utot(:,1);utot(1,1)],...
[vtot(:,1);vtot(1,1)],'ok');
a1 = plot([utot(:,i);utot(1,i)],...
[vtot(:,i);vtot(1,i)],...
'og','MarkerFaceColor','g');
set(gca,'Visible','off')
%
pause(0.001);
hold off
cla(ha)
M(i) = getframe; % use to create movie
end
axis([-2 aa -2 bb])
box off
set(gcf,'Color','w')
hold on
for l = 1:length(ConnMat)
hline(l) = line([utot(ConnMat(l,2),i) utot(ConnMat(l,3),i)],...
[vtot(ConnMat(l,2),i) vtot(ConnMat(l,3),i)],'Color','b');
end
% replots water and road after cla(ha)
set(hline(:),'Color','b','LineWidth',5)
rectangle('Position',[0,-2,aa-2,1],'FaceColor','c','EdgeColor','c')
rectangle('Position',[-2,-2,2,2],'FaceColor','k')
rectangle('Position',[aa-2,-2,2,2],'FaceColor','k')
47
a1 = plot([utot(:,end);utot(1,end)],...
[vtot(:,end);vtot(1,end)],...
'og','MarkerFaceColor','g');
end
function hselect_Callback(source,eventdata)
% Selects an existing bridge design or lets the user create his or her
own
value = get(hselect,'Value');
switch value
case 1
set(hselect,'String',{'....','Existing Bridge','Create New
Bridge'});
case 2
if(exist('fn')==0)|(fn==0)
fn='Documents\*.mat';
else
fn=['Documents\',fn];
end
[fn,pn]=uigetfile('Documents\*.mat','Specify the Bridge
Design Desired',fn);
name = [pn,fn];
guidata(f,fn)
fn_new = strrep(fn,'.mat','');
set(htext,'String',fn_new);
case 3
fn = uiputfile('*.mat','Specify the name of the Truss Design');
Truss_Drawing_GUI(fn);
end
end
function hsim_Callback(source,eventdata)
fn = guidata(f);
Simple_FEA_program(fn);
end
end
48
Appendix I: Truss_Drawing_GUI (truss drawing sub-function GUI)
function [] = Truss_Drawing_GUI(fid)
% This GUI function lets you draw new truss designs to be animated
f2 = figure('Visible','on','Position',[320,220,1280,600],'Resize','off');
set(gcf,'Color','w')
set(f2,'Name','Truss Design Manager')
% Create the components
hsize =
uicontrol('Style','popupmenu','String',{'......','Short','Meduim','Long'},...
'Position',[30,532,100,40],'Callback',{@hsize_Callback});
hsave = uicontrol('Style','pushbutton','String','Save',...
'Position',[360,540,100,45],'Callback',{@hsave_Callback});
set(hsave,'handlevisibility','off','Enable','off');
hreset = uicontrol('Style','pushbutton','String','Reset',...
'Position',[1160,540,100,45],'Callback',{@hreset_Callback});
set(hreset,'handlevisibility','off','Enable','on');
hpanel = uipanel(f2,'Units','pixels','Position',[20,540,120,50],...
'Title','Bridge Size','BackgroundColor','w');
hpanel2 = uipanel(f2,'Units','pixels','Position',[20,540,120,50],...
'Title','Select Bridge Size','BackgroundColor','w');
hbpanel = uipanel(f2,'Units','pixels','Position',[20,20,1240,510],...
'Title','Bridge Design','BackgroundColor','w');
hpanel3 = uipanel(f2,'Units','pixels','Position',[150,540,200,50],...
'Title','Draw','BackgroundColor','w');
hpanel4 = uipanel(f2,'Units','pixels','Position',[470,540,300,50],...
'Title','Message','BackgroundColor','w');
hnode =
uicontrol('Style','radiobutton','String','Nodes','BackgroundColor','w',...
'Position',[220,546,50,30],'Callback',{@hnode_Callback});
set(hnode,'handlevisibility','off','Enable','off');
helement =
uicontrol('Style','radiobutton','String','Elements','BackgroundColor','w',...
'Position',[280,546,65,30],'Callback',{@helement_Callback});
set(helement,'handlevisibility','off','Enable','off');
htext = uicontrol('Style','text','String','- - - - - - - - - - - - - - ','BackgroundColor','w',...
'Position',[480,550,280,20]);
ha = axes('Units','pixels','Position',[100,60,1100,450],...
'Visible','off');
set(ha,'handlevisibility','callback');
49
% Select Size of Truss layout and plots point layout and axes size
respectively
function hsize_Callback(source,eventdata)
value = get(hsize,'Value');
switch value
case 1
set(hsize,'String',{'....','Small','Medium','Large'});
case 2
cla(ha)
short = 15;
[X,Y] = meshgrid(0:short,1:10);
xbase = 0:5:short;
guidata(f2,X)
guidata(f2,Y)
guidata(f2,xbase)
plot(X,Y,'ok')
hold on
rectangle('Position',[0,2,short,1],'FaceColor','c','EdgeColor','c')
rectangle('Position',[-1,-2,1,2],'FaceColor','k')
rectangle('Position',[short,-2,1,2],'FaceColor','k')
for i = 1:length(xbase)-1
line([xbase(i),xbase(i+1)],[0,0],...
'Color','b','LineWidth',5);
end
plot(xbase,0,'og','MarkerFaceColor','g')
box off
axis([(min(min(X))-1) (max(max(X))+1) (min(min(Y))-3)
(max(max(Y))+1)])
save(fid,'xbase')
set(hsize,'Enable','off')
set(hnode,'Enable','on')
set(helement,'Enable','on')
case 3
cla(ha)
med = 30;
[X,Y] = meshgrid(0:med,1:15);
xbase = 0:5:med;
50
guidata(f2,X)
guidata(f2,Y)
guidata(f2,xbase)
plot(X,Y,'ok')
hold on
rectangle('Position',[0,2,med,1],'FaceColor','c','EdgeColor','c')
rectangle('Position',[-1,-2,1,2],'FaceColor','k')
rectangle('Position',[med,-2,1,2],'FaceColor','k')
for i = 1:length(xbase)-1
line([xbase(i),xbase(i+1)],[0,0],...
'Color','b','LineWidth',5);
end
plot(xbase,0,'og','MarkerFaceColor','g')
box off
axis([(min(min(X))-1) (max(max(X))+1) (min(min(Y))-3)
(max(max(Y))+1)])
save(fid,'xbase')
set(hsize,'Enable','off')
set(hnode,'Enable','on')
set(helement,'Enable','on')
case 4
cla(ha)
long = 45;
[X,Y] = meshgrid(0:long,1:20);
xbase = 0:5:long;
guidata(f2,X)
guidata(f2,Y)
guidata(f2,xbase)
plot(X,Y,'ok')
hold on
rectangle('Position',[0,2,long,1],'FaceColor','c','EdgeColor','c')
rectangle('Position',[-1,-2,1,2],'FaceColor','k')
rectangle('Position',[long,-2,1,2],'FaceColor','k')
for i = 1:length(xbase)-1
line([xbase(i),xbase(i+1)],[0,0],...
'Color','b','LineWidth',5);
end
plot(xbase,0,'og','MarkerFaceColor','g')
51
box off
axis([(min(min(X))-1) (max(max(X))+1) (min(min(Y))-3)
(max(max(Y))+1)])
save(fid,'xbase')
set(hsize,'Enable','off')
set(hnode,'Enable','on')
set(helement,'Enable','on')
end
end
% Lets the user place nodes on the point grid
function hnode_Callback(source,eventdata)
node = get(hnode,'Value');
if node == 1
set(helement,'Value',0)
i = 1;
X = guidata(f2);
Y = guidata(f2);
xbase = guidata(f2);
for i = 1:length(xbase)
Node(:,i) = [i;xbase(i);0]
end
j = 1;
k = 1;
while node == 1
[x,y,key] = ginput(1);
if (key == 'e')
set(htext,'String','Exited node selection.')
break;
elseif (key == 1)
set(htext,'String','Select node or press E to exit')
xn(k) = round(x);
yn(k) = round(y);
Node(:,k+length(xbase)) =
[k+length(xbase);xn(k);yn(k)]
plot(xn,yn,'og','MarkerFaceColor','g')
k = k+1;
else
set(htext,'String','Select node or press E to exit')
end
j = j+1;
end
52
guidata(f2,Node)
save(fid,'Node','-append')
set(hnode,'Value',0);
else
set(helement,'Value',1)
end
end
% Lets the user draw elements between the two nodes of their choosing
function helement_Callback(source,eventdata)
element = get(helement,'Value');
if element == 1
set(hnode,'Value',0)
data = load(fid);
xbase = data.xbase;
Node = data.Node';
for i = 1:(length(xbase)-1)
Element(:,i) = [i, i, i+1];
end
j = 1;
while element == 1
[x,y,key] = ginput(2);
if (key == 'r')
set(htext,'String','Exited element creation.')
break;
elseif (key == 1)
set(htext,'String','Select element points or press R
twice to exit')
xn(:,j) = round(x(1:2));
yn(:,j) = round(y(1:2));
% Find the nodes for the element selected
Node1x(:,j)
Node1y(:,j)
Node2x(:,j)
Node2y(:,j)
=
=
=
=
(Node(:,2)==xn(1,j));
(Node(:,3)==yn(1,j));
(Node(:,2)==xn(2,j));
(Node(:,3)==yn(2,j));
Node1(j) = find((Node1x(:,j) + Node1y(:,j))==2);
Node2(j) = find((Node2x(:,j) + Node2y(:,j))==2);
Element(:,j+i) = [j+i,Node1(j),Node2(j)];
53
plot([Node(Node1(j),2),Node(Node2(j),2)],[Node(Node1(j),3),Node(Node2(j),3)],
...
'-b','LineWidth',5);
hold on
for k = 1:length(Node(:,1))
plot(Node(k,2),Node(k,3),'og','MarkerFaceColor','g')
end
else
set(htext,'String','Select element points or press R
to exit')
end
j = j+1;
end
guidata(f2,Element)
save(fid,'Element','-append')
set(helement,'Value',0);
set(hsave,'Enable','on');
else
set(hnode,'Value',1)
end
end
% Resets the drawing window. Allows the user to restart.
function hreset_Callback(source,eventdata)
set(hnode,'Enable','off','Value',0)
set(helement,'Enable','off','Value',0)
set(hsize,'Enable','on')
set(hsize,'String',{'....','Small','Medium','Large'});
cla(ha); set(ha,'Visible','off')
close(clf)
Truss_Drawing_GUI
end
% Lets the user save the truss design. Name of saved file is that of
% what was chosen to use to create the truss in the first place.
function hsave_Callback(source,eventdata)
54
rho = 8000; E = 200e9;
A
= 3250/(1000^2);
save(fid,'rho','E','A','-append')
close(clf)
end
end
55
Download