I’ve started this section similarly to other sections – listing of programs first of all. However, on reflection It is my belief that it would be more useful to do away with the listing of programs, once the listing becomes extensive. I will simply provide a tar ball of the program, qrc files, sample data files and sample output files. The tar ball can be downloaded from:
Please download it and expand in a convenient directory. The program is in two parts: the GUI programming in PySide and the number crunching module. In fact, the two have been so designed that the “number cruncher” can be run as a simple CLI text program. This is very useful in the development stage, as it is possible to work with the two parts separately. As far as the extent goes, the GUI part (truss.py)is at least twice as big as the ncrunch.py module. The truss.py is some 380 lines long, though quite a large part of it is the book keeping and other notes. This is not large as far as programs are concerned, but it is too large to display here. It was a mistake in my planning to think that it could still be displayed.
Actually, many parts of the GUI program are paralleled in the earlier exercises: the about box is almost identical, as is the display of the licence. The GUI consists of two plainTextEdit widgets that are placed in a form with two tabs. One of these is for input, the other for the output. The output tab and the text editor are read only. The read only text edit widget can not be written to by hand, but will accept program output. We also do not want to allow loading of data or other information in the output text editor, so the program allows only Save As – saving of analysis results.
The analysis is of the simplest engineering structure – statically determinate truss which consists of pin jointed members, or members that are deemed to be pin jointed.. One of the ways that a simple statically determinate truss is analysed is by determining its external forces (including the reactions) by considering the whole truss as a freebody, then from equlibrium of pins of the joints member actions are determined. Because generally the coupling of the simultaneous equations is rather weak, it usually is possible to solve for memeber actions considering pins that are affected by only two unknown member forces. As there are two equilibrium equations at each joint (sum x 0 and sum y 0), the equations are usually solved by hand. There are however trusses with a peculiar set up of members that such simple solution is not possible. They are called complex trusses. We are limiting ourselves to statically determinate trusses only, which by definition means that the trusses can be solved solely by statics! In principle, for such structures we can always write equations for all pins of the structure, so that if the number of pins, or joints is j, the number of members is m and the number of reactions is r, then for the structure to be solvable by statics, the equation
- j * 2 == m + r
must apply. However, this is a necessary but not a sufficient condition, as it is possible for the structure to be a mechanism, unable to carry any external loads, in spite of the equation being satisfied. In computer analysis we callect all the equilibrium equations of the individual pins in to structure to a Connection Matrix.
Whilst it is easy for an experienced eye to recognise mechanisms, a strict more objective criterion for instability is that the Connection Matrix becomes singular. Some interesting investigation of this behaviour is possible with this program and you are encouraged to try it.
The program computes the condition number of the Connection Matrix. This is well outside the scope of this exercise, particularly in view of the fact that there are different “condition numbers” for the same matrix, depending on the norm that is used to derive the condition number. An interested reader is referred to texts on Linear Algebra for a more comprehensive treatment of this fascinating topic. Suffice it here to note that as the matrix approaches singularity, the condition number becomes much greater. The inverse of Connection Matrix and the condition number are calculated by numpy linearalgebra module.
Let us have a quick look at some parts of GUI program.
- def qprintline(self, line):
- '''Append one line to Solution Page.'''
This method appends one line to the Solution (Output) page and is passed to ncrunch module, so that ncrunch can print the results directly on the GUI page. Let us have a quick look at the part of the GUI that passes all data to ncrunch module and the qprintline method:
- def trussSolve(self):
- '''Solve a statically determinate truss, specified in
- Data Page and display the results in the Solution Page.
- To start, make a copy of the Data Page with a header all
- shown on the Data Page.'''
- printline = self.qprintline
- flbase = os.path.basename(self.filename)
- printline('SOLUTION FOR ' + flbase)
- dataBall = self.plainTextEdit.toPlainText()
- ncrunch.main(printline, self.filename, dataBall)
Notice that an alias printline is created for the qprintline method. The dataBall takes all the data from the Data Page. The TextEdit_2 – Solution Page is cleared and a header printed. To document the problem so as to avoid the confusion of “good solution for A” and another “good solution for B”. It quickly became apparent that the echo data check was confusing visually, so that a header needed to be printed.
As already mentioned, the header is indeed printed at the start of the trussSolve(self) method.
It is reasonable to wish to separate the GUI part of the program and the number crunching. It was already mentioned that in this program the number crunching part can run separately from the GUI. How this is done is shown in the next code snippet:
- if __name__ == '__main__':
- def printline(line):
- print line
This dummy function ensures that printline(line) prints on the console rather than on the Output Sheet in the tab2 of the GUI. The rest of the code is the normal CLI program to start the analysis. When the ncrunch.py
is used as a module, all after the coding after if name == ‘main’: is ignored. Conversely, when the ncrunch.py is run as the mainline, the truss.py is ignored. Thus, during the development the programmer deals with the two aspects – GUI and execution – separately, thereby substantially simplifying the work.
The rest of the code follows:
- print 'Usage: Give a name for data in the "dat" subdirectory'
- print 'as program parameter. Default is "sdtruss1.dat"'
- if len(sys.argv) > 1:
- name = sys.argv
- name = 'sdtruss1.dat'
- finput = open('dat/' + name, 'r')
- dataBall = finput.read()
- except IOError:
- print 'Failed to open given file name.'
- main(printline, name, dataBall)
A reasonable question that needs to be answered is: would the alternative of outputting the whole output in one operation be simpler? The answer is an emphatic NO. When the data preparation is more than a trivial task, mistakes must be expected. Outputting in piece meal manner the results as they become available helps to discover those mistakes early in the data preparation process and simplifies the mistake elimination.
Finally, one would hope that you will want to try this analysis with your own data. We would recommend to use an extant example as a template and substitute your own data. As the reactions are replaced by auxiliary members, ensure that all those members start at the structure itself, rather than the support. Also, number first the node on the structure, so that the numbers of nodes on the structure are contiguous and the “far” node of any auxiliary member is ignored as far as equilibrium equations are concerned.