Professional Documents
Culture Documents
Book of Examples
2018
University of Duisburg-Essen
Faculty of Engineering
Department of Civil Engineering
Structural Analysis of Plate and Shell Structures
Dr. E. Baeck
8.5.2018
Contents
2 Basics in Python 15
2.1 Code Convention . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.2 Reserved Words . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3 Packages and Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3.1 Import of a whole Module or Package . . . . . . . . . . . . . . . . . . . . . . . 16
2.3.2 Import all Names of a Module . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3.3 Selective Import of Module Names . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3.4 Import with new Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.4 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4.1 Unary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4.2 Arithmetic Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4.3 Bit Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.4.4 Extended Assign Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.4.5 Manipulating Bits and Hexadecimal Numbering System . . . . . . . . . . . . . 20
2.4.6 Comparison Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.4.7 Membership Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.4.8 Identity Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.5 Print and Output Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.6 Basic Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
iii
Page iv Analysis of Structures - SS 15
3 Python Projects 61
3.1 Newton, Step2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.2 Profiles, Thin Walled Approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
3.2.1 A General Base Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
3.2.2 A Node Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
E. Baeck
CONTENTS Page v
8.5.2018
Page vi Analysis of Structures - SS 15
D Conventions 141
D.1 The Java Code Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
E. Baeck
CONTENTS Page 1
8.5.2018
Page 2 Analysis of Structures - SS 15
E. Baeck
Part I
3
1
The name Python has nothing to do with the snake of the same name. The name
Python was taken from the British surreal comedy group Monty Python (see figure
1.2). Because the Monty Python is hard to symbolize onto an icon, the python
snake came into picture and so on all icons and Python symbols today we can see
Figure 1.1: the snake.
Guido van Rossum
The Python language is highly dynamic, so the language is able for example to
create it’s source code by itself during runtime. This fact and it’s highly portability are reasons for it’s
interpreted kind.
1
This is only true, if no platform depended packages like comTypes are used.
5
Page 6 Analysis of Structures - SS 15
If we start with Python, we should think about the choice of the Python version. Because we will use
some additional Python packages, we should be sure, that this packages are available for the desired
Python version. In the case of our lecture we will select the Python version 2.6, which is properly stable
and furthermore all the needed add-on packages are available.
To start from the beginning, we have to download the following packages for windows first. It is rec-
ommended to download the windows installer version, if available because this is the easiest kind of
installation. The installation procedure should start with the installation of the kernel package.
• python-2.6.4.msi
The installer of the python kernel system 2.6.
• comtypes-0.6.2.win32.exe
The installer of Windows types, which are necessary to use Windows API-calls.
• numpy-1.4.1-win32-superpack-python2.6.exe
The installer of the NumPy package for numerical programming.
• scipy-0.8.0-win32-superpack-python2.6.exe
The installer of the SciPy package for sientific programming.
• matplotlib-0.99.3.win32-py2.6.exe
The installer of the MatPlotLib package. This package we need to get the pylab package.
• pywin32-214.win32-py2.6.exe
The installer of a little nice Python IDE.
The python kernel should be the first package, which is to install, because this installation sets up the
Python base folder. Within this folder you can find the folder Lib, which contents a lot of libraries and
additional packages and besides that a further sub folder called site-packages. Add ons are copied into
this folder by their installers or by the install Python script.
The start screen of the Python installer shows the Python version. You can select, whether the setup
should make Python available for all users or not. After clicking next you’ll get within the second form
the possibility to select the base folder of Python. By default Python uses the folder C:\Python26.
We overwrite the default and select the Windows standard program folder as starting folder, so we write
c:\Programme\Python2623 .
The figures 1.3 and 1.4 show the input forms installing the Python kernel.
If you want to use the Python language on a Windows system, it’s recommended to install the ComTypes
package. This package will give you a simple access to the Windows resources. It can be understood as
2
The discussed installation was performed on a German system.
3
The installation of newer packages is working in the same way.
E. Baeck
1.2. PYTHON, PACKAGES, UTILITIES Page 7
Figure 1.3: Start Screen of the Python Installer and Choice of Base Folder
a wrapper layer, an interface layer for the access to Windows DLL-modules. ComTypes can be a help to
develop a software with a proper Windows look and feel.
The installation of the most Python packages will run very simular to the following installation. The
figures 1.5 show the first and second form of the installation procedure. The first form gives a few
information to the package. The second form is usually used to select the Python version. Each installed
and supported Python version will be listed in the list box of the second form. You can select the desired
Python version and can go on with the installation procedure clicking the next button.
NumPy [2] is the fundamental package for scientific computing in Python. It is a Python library that pro-
vides a multidimensional array object, various derived objects (such as masked arrays and matrices), and
an assortment of routines for fast operations on arrays, including mathematical, logical, shape manipula-
tion, sorting, selecting, I/O, discrete Fourier transforms, basic linear algebra, basic statistical operations,
random simulation and much more.
At the core of the NumPy package, is the ndarray object. This encapsulates n-dimensional arrays of
8.5.2018
Page 8 Analysis of Structures - SS 15
Figure 1.5: Start Screen of the Package Installer and Choice of the installed Python Version
homogeneous data types, with many operations being performed in compiled code for performance.4
The installation runs like the installation of the ComTypes package (see figure 1.6).
Figure 1.6: Start Screen of the Package Installer and Choice of the installed Python Version
4
For more details see NumPy User Guide available on the info.server.
E. Baeck
1.2. PYTHON, PACKAGES, UTILITIES Page 9
SciPy [3] is a collection of mathematical algorithms and convenience functions built on the Numpy ex-
tension for Python. It adds significant power to the interactive Python session by exposing the user to
high-level commands and classes for the manipulation and visualization of data. With SciPy, an inter-
active Python session becomes a data-processing and system-prototyping environment rivaling sytems
such as Matlab, IDL, Octave, R-Lab, and SciLab.
The additional power of using SciPy within Python, however, is that a powerful programming language
is also available for use in developing sophisticated programs and specialized applications. Scientific
applications written in SciPy benefit from the development of additional modules in numerous niche’s
of the software landscape by developers across the world. Everything from parallel programming to web
and data-base subroutines and classes have been made available to the Python programmer. All of this
power is available in addition to the mathematical libraries in SciPy.5
The installation runs like the installation of the ComTypes package (see figure 1.7).
Figure 1.7: Start Screen of the Package Installer and Choice of the installed Python Version
5
For more details see SciPy Reference Guide available on the info.server.
8.5.2018
Page 10 Analysis of Structures - SS 15
To create Python sources we need at least a simple text editor like Notepad++ or PSPad6 like for every
computer language. This source files with the standard extension py, like helloworld.py, can be
executed starting the Python interpreter.7
1 c:\pyhton27\python helloworld.py
For Windows there is a lightweigth IDE available called PythonWin. PythonWin looks like an extension
to the MS-Editor Notepad. To create and check small Python scripts, this IDE seems to be ok, because
the overhead we have to overcome is very small compared to really good IDEs.
The installation of PythonWin runs like the installation of the ComTypes package (see figure 1.8).
Figure 1.8: Start Screen of the PythonWin IDE Installer and Choice of the installed Python Version
After having installed the PythonWin IDE it’s recommended to set up a link onto the desktop (see figure
1.9).
Figure 1.10 shows, how to create a Hello World application in Python and the application’s execution.
Within the editor window, we write the source code. With the start button (black triangle) we can run the
Hello World from the PythonWin. The applications screen output is written into the Interactive Window,
which also is working as a Python console.
6
Notepad++ and PSPad are available on the info.server in /Software/Editors.
7
In this case the Python 2.7 was installed into the Folder c:/Python27.
E. Baeck
1.2. PYTHON, PACKAGES, UTILITIES Page 11
There is not only one Python implementation available. The original implementation is written in C. It’s
the reference implementation, developed by Guido van Rossum, called CPython too.
Jython (or JPython) is an implementation of the Python language in Java. The interpreter therefor is
running on a Java environment and is able to use all Java libraries.
IronPython is an implementation for the Common-Language-Infrastructure (CLI), i.e. for the .Net en-
vironment on Windows or for the compatible environment Mono on Linux. IronPython is written in C#
and is available in a CLI language (like C#) as a script language. IronPython is compatilble to CPython’s
version 2.7.
PyPy is a Python interpreter, which is implemented using the Python language. It’s used as an experi-
mental environment to develop new features.
8.5.2018
Page 12 Analysis of Structures - SS 15
Like in every computer language there is a Hello World application in Python also possible. We start
dhe PythonWin IDE and create a new file. We save this file as HelloWorld.py. With Ctrl-R the execution
form is shown and the execution mode should be selected (see figure 1.11).
• No debugging,
execution without debugging.
If the HelloWorld.py script is executed, the output is written into the Interactive Window, see figure 1.10.
E. Baeck
1.4. PYTHON CALCULATOR Page 13
One of Python’s advantages is the feature to execute only one statement within the Python shell. The
Python shell within the PythonWin IDE is given by the Interactive Window, see figure ??.
If we want to calculate the vertical position of a ball thrown up in the air with an initial velocity v0 after
a time t we get from the Newton’s law
1
y(t) = v0 · t − · g · t2 (1.1)
2
So, if we want to calculate the vertical position for an initial velocity v0 = 5m/s after 0,6 seconds, we
can calculate the y(t = 0, 6) with one simple Python call.
1 >>> print 5*0.6 -0.5*9.81*0.6**2
2 1.2342
3 >>>
A second version of the calculation can be performed introducing and using variables as follows. So we
can check every Python command within the Interactive Window.
1 >>> v0 = 5
2 >>> g = 9.81
3 >>> t = 0.6
4 >>> y = v0*t - 0.5*g*t**2
5 >>> print y
6 1.2342
7 >>>
A third version of our calculation of the ball’s height could be a Python script, which we can load and
executed within the PythonWin IDE. To comment the code we insert some comments, which starts with
the # character. Characters at the right side of the # character are ignored by the Python interpreter.
8.5.2018
Page 14 Analysis of Structures - SS 15
E. Baeck
2
Basics in Python
In modern programming languages we can use nearly arbitrary names for variables, for functions, classes
and packages. Of course the names should be clear, i.e. the should not ambiguous. Sometimes however
it’s helpful to select names according to a name convention. If we use a name convention, we can put an
additional information into an item’s name, so that a developer can get this information without knowing
the details behind the code.
One of the first conventions was introduced by Charles Simonyi, a Hungarian software engineer, who
worked at Xerox PARC and later with Microsoft. This convention therefore is called Hungarian Notation.
The Hungarian Notation inspired from FORTRANs implicit name convention too, introduces some name
prefixes, which should show the developer some information about the variable usage.
With the emergence of the language Java a new code convention was introduced, which today is used in
many applications, so for example in the implementation of the Abaqus Python Interface. This we will
discuss in the second part (II). A short extract from this code convention, published by Sun Microsystems,
Inc. in 1997, we see in the appendix D.1.
4. If names consists of several parts, we introduce every part except the first with a capital letter. This
is called camelCase, because of the shape of the camel’s back, the camel hump. Of course we do
not use white spaces inside the names, because this is not allowed.
15
Page 16 Analysis of Structures - SS 15
We have seen in section 1.4, starting with a Python calculation within the Python shell is very easy. We
can use simple formulas with numbers or we can use symbolic names to make it more readable. In
Python like in other programming languages there are some reserved word, which are used to build up
the language. This words can not be used as variable names.
If you want to use such a word it’s recommended to extent the name with an underscore, like vor example
break_ instead of break.
A package within Python is a container of software objects, global variables, functions and objects. In C
or Fortran, a package could be termed as library.
Packages should be imported into the Python session or into the Python source file, if external feature
should be used. A typical package import is the import of the mathematical package. This is necessary
if you want to call some basic mathematical functions like trigonometric functions or the square root. If
such a package is not imported, it’s objects, especially it’s functions, are unknown and can not be used.
Packages are like header includes within the C language. In C as well, external functions, whose headers
are not included, are unknown and can not be called.
A whole package is imported with the statement "import" module. The following example shows
the import of the mathematic package to apply the square root function. With the import statement the
module math will be linked. The square root function sqrt will be then available with the usual dot access
math.sqrt.
E. Baeck
2.3. PACKAGES AND MODULES Page 17
If we only want to import all symbolic name of a module (package), we use the star as a wild card. The
following example shows the import of all names of the module math. If we do this, we can use all
functions of the module without prefixing it.
1 >>> from math import *
2 >>> sqrt(4)
3 2.0
4 >>> fabs(-2.)
5 2.0
If we only want to import a symbolic name of a module (package), then we can import in a selective
way. The nex example shows the selective import of the function sqrt from the module math. If we do
this, then the function can be used without the prefixing module name.
1 >>> from math import sqrt
2 >>> sqrt(4)
3 2.0
4 >>>
If some names of of module should be imported with new names, the statement as can be used within
the import statement. The following example shows the import of the trigonometric functions sin and
cos with the new names s and c and the constant pi with it’s original name, to calculate the Cartesian
ordinates of a 45 point with radius 10.
1 >>> from math import sin as s, cos as c, pi
2 >>> r = 10
3 >>> x = r*c(pi/4)
4 >>> y = r*s(pi/4)
5 >>> x
6 7.0710678118654755
7 >>> y
8 7.0710678118654746
9 >>>
You see, that we change the original name of the trigonometric functions with the as key word. Within
the formulas the functions can be used with it’s new names.
8.5.2018
Page 18 Analysis of Structures - SS 15
2.4 Operators
We have already seen, that Python also has it’s operators calculation the height of a vertical thrown
ball. Python uses the same precedence as we know form the mathematics. The power operation has the
strongest binding followed by the point operators (products and divisions) followed by the line operators
(plus and minus). Unary operators will always be applied first. To change the standard precedence of the
operators we use like in mathematics parenthesis to dictate the way a formula should be evaluated.
Unary operators are working only on one value, therefor unary. In Python there are three unary operators
available.
The bitwise inversion shows the internal representation of negative numbers. A negative number is
represented by the so called b-complement of a number. This is the complement, i.e. the bitwise inverted
number plus 1. So we get
−a =∼ a + 1 or ∼ a = −(a + 1) (2.1)
Python offers the following arithmetic operators. You should be careful with the usage of data types
especially within divisions. If you use integers, the result generally will be truncated.1
1
The exception of the power operator all the arithmetic operators are used with the same symbol like in C. In C there is no
power operator available.
E. Baeck
2.4. OPERATORS Page 19
Like in C bit operators can be easily be used to manipulate a number’s bits. The following operators are
available2
The left shift of a numbers bit by 1 is equal to a multiplication by 2. The right shift by one is the same as
a division by 2. The bitwise AND and OR operator are usually used to set or to clear a number’s bits.
The following example shows how to apply the shift operator. We start with the bit 0, which has the
value 1. Within a for loop (see section 2.9) the bit is shiftet subsequently to the left. So we create the bits
in the range from n to m. After shifting the bit, it’s value is printed into the console window.
An extended assign operator combines the effect of an operator with the assignment to the involved
variable. This is inherited from the language C. In the table below we start with a variable x = 2.
2
Python’s bit operators are exactly the some as the C bit operators.
8.5.2018
Page 20 Analysis of Structures - SS 15
If we want to manipulate a number’s bits it is obvious more clearly to use the hexadecimal representation
of a number as using the elsewhere usual decimal representation. Hexadecimal numbers starts with the
literal 0x3 and uses the digits 0-9 and A-F. F is with 15 the largest digit of the hexadecimal numbering
system. The hexadecimal numbering system has the advantage, that it packs 4 bits of a number into one
hexadecimal digit. So a byte can be represented by 2 hexadecimal digits. If we now be able to translate a
hexadecimal digit into a binary number, then we can see even the bits in the largest number without any
calculation.
In the following example we want to analyze the arbitrary number 27563. The bits are obviously very
hidden using the decimal representation. To get a hexadecimal representation we can simple print the
number using the X formating. We can see that we obviously use two bytes for this number, because wie
get 4 digits (6BAB). Furthermore we can see, that the leading bit is not set, because the largest digit is 6
and the highest bit in a digit has the value 8.
1 >>> a = 27563
2 >>> "%X" %a
3 ’6BAB’
4 >>>
The binary number representation is easily available from the hexadecimal representation, if we know
the binary representation of the hexadecimal digits4 .
So we get assembling the binary digits of 6BAB the following bit sequence.
If we now want to set the highest bit of the discussed number, we can use the bitwise OR operator | (see
section 2.4.4). A number with only the highest bit set we can obtain by shifting the first bit to the desired
position within the 2 bytes, i.e. we shift the bit 15 times. Now we can see that we get a hexadecimal
number with only the highest digit non vanishing. Within the digit of 8 the forth bit is set, which is the
highest of a have byte5 .
1 >>> b = 1
2 >>> b = b<<15
3 >>> b
4 32768
5 >>> "%X" % b
6 ’8000’
If we now want to set the highest bit of our original number 27563, we simple can overlay it with the last
number 8000.
3
A binary number starts with the literal 0b and uses the digits 0 and 1, like 0b1000 = 810 .
4
The index of the example’s numbers represent the base of the numbering system.
5
A half byte is also called nibble.
E. Baeck
2.4. OPERATORS Page 21
1 >>> a = 27563
2 >>> b = a | (1<<15)
3 >>> b
4 60331
5 >>> "%X" % b
6 ’EBAB’
After having set the highest bit, we see that the decimal number has changed totally. However the
hexadecimal number only changes in the first digit. Instead of 6 we have now E. And E is represented
binary with
E16 = 1410 = 8 + 4 + 2 = 11102
so we get
6033110 = EBAB16 = 1110|1011|1010|10112 (2.3)
Comparing the binary result with the binary result of equation 2.2 we see that obiously only the first bit
is set as wanted.
How we can now clear a bit of a number? Clearing a bit of a number uses two steps. First we have to
create the inverse of the filtering number, having set only the desired bit. And within a second step we
use the AND operator & to overlay bitwise the inverse of the filtering number and the number, whose bit
should be cleared. In our example we want to clear the highest bit of the first byte. The filtering number
we get shifting the 1st bit 7 times.
1 >>> a = 27563
2 >>> b = a & (˜(1<<7))
3 >>> b
4 27435
5 >>> "%X" % b
6 ’6B2B’
We also notice, that the decimal representation has changed widely after the clearing of the bit on the
contrary to the hexadecimal.
2743510 = EB2B16 = 1110|1011|0010|10112 (2.4)
Boolean operators are used to branch and to make decisions. The comparing operators are identical to
the C comparing operators.6
8.5.2018
Page 22 Analysis of Structures - SS 15
The result of a boolean expression like above are the boolean values False or True. To combine
comparing expressions the following logical operators can be used.7
The following table shows the truth values of the && and the || operator.
With the membership operators you can check whether a value or an object is part of sequence of objects.
With the identity operators you can check the identity of two objects.
7
To make expressions clear parenthesis should be used. A term within a parenthesis is evaluated first and it’s result then is
used in further evaluations outside the parenthesis. With parenthesis the order of the evaluation can be set.
E. Baeck
2.5. PRINT AND OUTPUT FORMATS Page 23
If you want to print data into the console window, you have to think about formating. The formating
sequences are very similar to the formating sequences of the C printf function. The formating is a so
called escape sequence within a string, which is started with the % operator.
• formating an integer
An integer (independent of the data type) is formated by the escape %d for decimal representation
and %x or %X for hexadecimal representation.
• formating a float
A float is formated by the escapes %f, %e, %E, %g and %G
• formating a string
A string is formated by the escapes %s
A leading number n within a format %nT, with T the type of the format, sets up the width of the output.
The following example shows the formating of an integer in decimal and hexadecimal mode. At the
hexadecimal format a lower x sets lower digit letter, the capital X sets capital digit letters.
1 >>> "%d,%3d,%6d" % (2,2,2)
2 ’2, 2, 2’
3 >>> "%x,%3X,%6X" % (31,31,31)
4 ’1f, 1F, 1F’
Formating floats there are two different formats available, the fixed format and the exponential format,
which is also called scientific format. The f format sets a non exponential representation. The e or E
format sets a exponential format. e uses a small e letter, and E uses a capital E letter. The g or G format
sets an optimized representation, i.e. a fixed or an exponential format, depending on the outputs length.
The number after the dot sets the number of digits after the comma for f and e format, it sets the number
of significant digits for the g format.
1 >>> "%f,%e,%g" % (12.34,12.34,12.34)
2 ’12.340000,1.234000e+01,12.34’
3 >>> "%.2f,%.2e,%.2g" % (1234567.89,1234567.89,1234567.89)
4 ’1234567.89,1.23e+06,1.2e+06’
8.5.2018
Page 24 Analysis of Structures - SS 15
Recording to the available data types, Python is very different comparing it with common languages like
C, Fortran and Basic. Most of the languages offers the programmer data types, which are one by one
related to the underlaying hardware.
So for example Fortran and C offer 2 and 4 byte integers on 32 bit operating systems by default8 On a
64 bit operating platform a long integer of 8 bytes will be available. On the other hand there are 4 and 8
byte floats available.
Python however offers on 32 bit platforms a normal integer of 4 bytes, which is directly related to the
hardware, for example 11234, and furthermore a so called long integer, for example 1234L, which is
handled by the Python software. The long integer, which is marked by a succeeding L, is only restricted
by the computers memory, that means that a really incredible number of digits can be considered. Later
we will calculate the factorial of a incredible high number.
Furthermore Python as already mentioned offers only one float data type with 8 bytes. The standardized
4 byte float is not supported, for example 1.23 or 1.23e+2.
Python also supports a complex arithmetic with an complex data type, consisting of two floats for real
and imaginary part of the complex number. The complex unit in Python is called j. Therefor the complex
number 1 + 4i will be represented in Python with 1 + 4j.
The last data type used in Python is a string consisting of one or more characters.
The data type of a variable can be determined using the build in function type, as shown in the following
example. Within a first step different variables were created by a simple assignment. The content of the
variable determines the type of the variable, no explicit declaration is needed or available, like in C. After
having created the variables the type of the variables will be determined by subsequent type calls.
To check the data type within a program the following tests can be made.
1. if type(d).__name__ == ’int’
You can check the type with the types __name__ member.
2. if type(d) == int
... or you can check the type with the type class name (discussed later).
1 >>> a = 2
2 >>> b = 3L
3 >>> c = 4.5
4 >>> d = 6 + 7j
5 >>> e = "Hello World"
6 >>> type (a)
7 <type ’int’>
8 >>> type (b)
9 <type ’long’>
10 >>> type (c)
11 <type ’float’>
12 >>> type(d)
13 <type ’complex’>
8
That means without applying provider depended tricks.
E. Baeck
2.7. CODE BLOCKS Page 25
14 >>> type(e)
15 <type ’str’>
You see, ’int’ is integer, ’long’ is long integer, ’float’ is float, ’complex’ is complex and
’str’ is string data type.
Furthermore there are some sequences in Python available, which combines the mentioned data types in
a more or less sophisticated mode. More about that later.
One very imported feature of Python is, that code blocks are bracketed by an unique indent. The most
programming languages uses there specific code parenthesis. There is one opening parenthesis which
starts the code block and there is one closing parenthesis, which closes the code block.
Compared with this in Python the code block is bracketed by indent as follows.
1 if a > b:
2 c = a + b
3 d = a - b
4 ... Further Lines of Python-Code ...
5 a = b
One statement which uses a code block, in this case an if statement, is closed by a colon. After the colon
an unique indent for the lines of the code block must be used. If not, it will be a syntax error. The code
block is closed, if the last line of the code block is the last line of the whole code, or is closed by a line
of code which is indented like the opening statement. In our example the assignment a=b has the same
indent as the if statement and so this line will be the first line of code outside our code block.
8.5.2018
Page 26 Analysis of Structures - SS 15
2.8 Globales
In Python a variable will be created, if an assignment is done. If so, it is impossible to access a variable,
which is introduced elsewhere, i.e. a global variable. If we now want to access such a variable, we have
to declare it inside our local function as a global variable. If we do this, the Python interpreter is looking
for a variable with such a name inside the name space of the calling function.
Example 2.2 shows how to access a global variable and which effect we have, if the value is changed
inside the called function.
1 # usage of global
2
3 def doSomething(a):
4 global b
5
8 a = 10 # local variable
9 b = 20 # global variable
10 c = 30 # local variable
11 print "doSomething...: a = %d, b = %d, c = %d" % (a,b,c)
12
13 a = 1
14 b = 2
15 c = 3
16 print "before calling: a = %d, b = %d, c = %d" % (a,b,c)
17 doSomething(a)
18 print "after calling.: a = %d, b = %d, c = %d" % (a,b,c)
1 before calling: a = 1, b = 2, c = 3
2 doSomething...: a = 1, b = 2
3 doSomething...: a = 10, b = 20, c = 30
4 after calling.: a = 1, b = 20, c = 3
In the output listing from our little testing example 2.2 we see, that the value of the global variable b
is overwritten by the function call, the value of the local variable a only is changed inside the function.
After the function call we see, that the variable a remains untouched by the function call.
E. Baeck
2.9. LOOP FOR REPETITIONS Page 27
Like all programming languages, which make sense, Python also has some implementations of repe-
titions, of loops. Like in C an explicit loop is available - the for loop - as well as an implicit loop is
available - the while loop.
The for loop is controlled by an iterated set. One very common variant is the for loop, which is controlled
by an iteration counter. The iteration counter will be configured by a range object. The range object has
3 parameters9 . The first parameter sets the start value of the iteration counter, the second parameter sets
up the iteration value, which will be the first value that is not performed. The third parameter sets up the
increment.
The following typical example for the usage of an iterative for loop implements the calculation of the
factorial.
n
Y
n! = i (2.5)
i=1
The implementation of the factorial is given below. Note the importance of the indent, see section 2.7.
1 n = 10 # factorial input
2 p = 1 # result variable must be initalized by 1
3 for i in range(2,n+1): # the counter runs from 2 up to n
4 p *= i # here we perform the product
5 print "%3d! = %10d" % (n,p) # write the result into the console
6
The second loop type, the while loop is working implicit with a boolean expression, which controls the
break condition. If we want to implement the factorial using the while loop we get the following code.
1 n = 10 # factorial input
2 p = 1 # result variable must be initalized by 1
3 i = 2 # the counter runs from 2 up to n
4 while i <=n: # loop with break condition
5 p *= i # perform the product
6 i += 1 # explicit incrementation
7 print "%3d! = %10d" % (n,p)
8
9
A parameter is a information unit, which is passed to the called object. If more then one parameter is passed, the parameters
are separated by commas.
8.5.2018
Page 28 Analysis of Structures - SS 15
The next example shows a nested loop. Very important is the correct code block indent.
1 for i in range(0,4): # outer loop
2 for j in range(0,2): # inner loop
3 print "i:%2d, j:%2d" % (i,j) # print counter variables
4
For the detailed controlling of the loops cycles two statements are available.
• continue
If the continue statement is used a cycle is immediately stopped and the next cycle is started.
• break
If the break statement is used a cycle is immediately stopped and the loop is exited.
The next example shows an application of the continue statement. A loop is performed with the values
0 · · · 4. The cycle with the counter 2 is prematurely canceld.
1 >>> for i in range(0,5):
2 ... if i == 2: continue
3 ... print "i=%d" % i
4 ...
5 i=0
6 i=1
7 i=3
8 i=4
One very interesting feature of Python is the long integer arithmetic. So we can calculate incredible large
factorials. Figure 2.1 shows the code in the upper window. The console window shows the result. A
number with a lot of digits and every digit is exact.
The next example shows the calculation of the factorial using a float. The float factorial can only be
evaluated up to 170! = 7.25742e+306. In the case of 400! we will get an overflow, because the
exponent exceeds the available memory in 8 bytes (see figure 2.2).
E. Baeck
2.9. LOOP FOR REPETITIONS Page 29
8.5.2018
Page 30 Analysis of Structures - SS 15
The Precision-Finder is a nice little program, which analysis the relative precision of a given float format.
Stop
E. Baeck
2.10. FUNCTIONS Page 31
2.10 Functions
A function is a callable type. A function starts with the def command. The parameter list succeeds the
function name and consists of names separated by commas. The return of return values is optional. If
more then one return value should be given, the return values are separated by commas and the calling
code will get a tuple containing all the return values. A single return value is not returned in a tuple.
A nice example to study cases of a solution and their specific return values is discussed in section 2.11.
1 def <name> (Parameter list):
2 Code Block
3 return <Return Object list>
Listing 2.4 shows two functions with two parameters. The first function returns 3 values in a tuple, the
second function returns only one value. This value is returned without a tuple.
Runing the code of listing 2.4 will print the following output.
1 return of myFunction1... : (2, 3, 8)
2 length of returned tuple : 3
3 return of myFunction2... : 8
4 return of myFunction3... : (8,)
5 length of returned tuple : 1
8.5.2018
Page 32 Analysis of Structures - SS 15
Decisions are made by the usage of the if statement. The if statement is defined as follows.
1 if [boolean expression 1]:
2 code block 1
3 elif [boolean expression 2]:
4 code block 2
5 elif [boolean expression 3]:
6 code block 3
7
8 ...
9 else:
10 code block else
Like in languages like C/C++ in Python there is a similar conditional assignment available.
1 <variable> = <value_1> if <boolean expression> else <value_2>
In listing 2.12 we get an i value of 3, because b is true. Otherwise we would get a zero value.
1 b = true
2 i = 3 if b else 0 # in C: i = b ? 3:0;
The calculation of roots of a quadratic equation is a nice and simple example to show the application of
the if statement. The quadratic equation is given by
a · x2 + b · x + c = 0 (2.6)
If we want to solve the quadratic equation, we have to analyze the available cases. A general solution
must handle the following cases.
• constant case
a=b=c=0
• linear case
a = 0, b 6= 0
• quadratic case
a 6= 0
• no solution case
a = b = 0 and c 6= 0
E. Baeck
2.12. CONDITIONAL ASSIGNMENTS Page 33
2.12.1.1 A Flow-Chart
The following flow chart shows all the case, which we have to handle. The algorithm is given for a real
arithmetic, i.e. no complex data types are used. The relevant source code will be developed within the
next section.
Start
no no no
yes √
−b±i −d
d<0 x1,2 = 2·a
Stop
no
√
−b± d Stop
x1,2 = 2·a
The implementation uses a real as well a complex arithmetic importing the module math and cmath. The
solver of the quadratic equation is implemented in a function called QuadSolve. The function analyzes
the different cases and returns in the constant case only a comment, in the linear case the solution value
and a comment. In the quadratic case 2 values and a comment were returned. All return values are
packed into a tuple. The case can be identified form the calling program using the function len, which
returns the number of items of a tuple. To branch in the real respectively the complex quadratic case, we
have to check the type of the returned result values using the Python function type. This we see in line
75. If the type is complex, we have to extract the real and the imaginary part of the number, to print it
using the print statement.
From line 44 on, we can see that using the complex square-root function cmath.sqrt automatically we
get a complex result. So it’s possible too, to return in any quadratic case a complex results. If so, we
don’t need to branch.
To avoid the testing for zero, which would produce numerical problems in principle, we set the relative
precision to 10−15 . An absolute value less then this relative precision is treated as zero value. Here we
apply the function fabs from the math package introducing the alias abs. Here we should know, that
Python provides a buildin function abs, which then will be overlayed by the fabs, so that the buildin is
visible no more.
8.5.2018
Page 34 Analysis of Structures - SS 15
1 ’’’
2 solution of a quadratic equation
3 - handling all special cases -
4 ’’’
5 # import the used functions
6 from math import fabs as abs, sqrt
7 import cmath
8
9 def quadSolve(a,b,c):
10
14 # case: a=0
15 if abs(a) < p:
16
17 # case: b=0
18 if abs(b) < p:
19
20 # case: c=0
21 if abs(c) < p:
22 return ("Infinit number of solutions.",)
23
24 # case: c!=0
25 else:
26 return ("No solution possible.",)
27
37 # real case
38 if d >= 0.:
39 s = sqrt(d)
40 x1 = 1./(2.*a)*(-b +s)
41 x2 = 1./(2.*a)*(-b -s)
42 return (x1,x2,"Real case of the quadratic problem.")
43
44 # complex case
45 else:
46 s = cmath.sqrt(d)
47 x1= 1/(2.*a)*(-b +s)
48 x2= 1/(2.*a)*(-b -s)
49 return (x1,x2,"Complex case of the quadratic problem.")
50
E. Baeck
2.13. FUNCTION EXAMPLES Page 35
55 c = 4.
56
69 # linear case
70 elif values == 2:
71 print "x = %f, info: %s" % result # (result[0],result[1])
72
73 # quadratic case
74 elif values == 3:
75 if type(result[0]) == complex:
76 print "x1 = %f+(%fi), x2= %f+(%fi), info: %s" \
77 % (result[0].real,result[0].imag,
78 result[1].real,result[1].imag,
79 result[2])
80 else:
81 print "x1 = %f, x2 = %f, info: %s" % result
In this section we will discuss a new abs function and the Newton algorithm using a function as parameter.
The following code shows a special version of the abs function. The data type is checked first. Only int,
long or float type are senseful supported. We check the type with the type function. The type function
returns a type object. Within the function we check the object member __name__. If the type is not
supported, a error string is returned. If the type is supported, the return value is return. The calling
program checks the return values type using the object name (int, long and float).
8.5.2018
Page 36 Analysis of Structures - SS 15
15 # input section
16 y = -4 # test 1
17 # y = "hello" # test 2
18
19 # function call
20 z = myAbs(y)
21
E. Baeck
2.13. FUNCTION EXAMPLES Page 37
There are three possible situations to handle within the iteration loop.
• The function value is vanishing with respect to our selected precision. The iteration loop will be
broken and the found result is passed back to the caller.
• The slope of the function is vanishing. This situation can not be handled by the simple iteration
scheme. The iteration will be broken with an error message.
• During the iteration each cycle is counted. So the iteration loop will be broken, if the maximum
available iterations are reached. The actual values and an error message is passed bake to the caller.
The following flow chart is given for a simple implementation of Newton’s algorithm.
Start
Initializing:
x = x0 ; i = 0;
yes
i ≥ imax NO ROOT! Stop
no
F x = f (x)
yes
|F x| ≤ ROOT: x Stop
no
F s = f 0 (x)
yes
|F s| ≤ NO SLOPE! Stop
no
Fx
x = x− Fs
i = i+1
8.5.2018
Page 38 Analysis of Structures - SS 15
• fs, the function which calculates the slope of a given function numerically.
22 i = 1 # iteration counter
23 while True:
24
E. Baeck
2.14. DATA SEQUENCES Page 39
• Tuples are fixed sequences, which are only extensible. The advantage of tuples is the performance.
The following example shows the creation of a tuple. An empty tuple is declared. We extend the tuple
with a one element tuple - note the comma. The second extension extends the tuple with a two element
tuple.
1 >>> t = () # initialize the tuple
2 >>> t
3 ()
4 >>> t += (1,) # append the tuple with a number
5 >>> t
6 (1,)
7 >>> t += (2,3) # append at tuple with a second tuple
8 >>> t
9 (1, 2, 3)
10 >>> t[0] # calling the tuple’s first element
11 1
12 >>> t[2] # calling the tuple’s third element
13 3
14 >>> t[3] # an error occur, if the index goes out of range
15 Traceback (most recent call last):
16 File "<interactive input>", line 1, in <module>
17 IndexError: tuple index out of range
18 >>> len(t) # the number of elements is given by the len function
19 3
8.5.2018
Page 40 Analysis of Structures - SS 15
Note, that tuples are input data for complex string formatings.
With the function tuple() a tuple can be created from an iterable object like string or list.
1 >>> T =tuple([1.,2.])
2 >>> T
3 (1.0, 2.0)
4 >>> L = list(T)
5 >>> L
6 [1.0, 2.0]
7 >>> T = tuple("Hello World")
8 >>> T
9 (’H’, ’e’, ’l’, ’l’, ’o’, ’ ’, ’W’, ’o’, ’r’, ’l’, ’d’)
Note, that the data of a list can be converted into a tuple using the function tuple() and reverse into a
list using the function list().
Lists are more flexible as tuples. Creating and extending lists can be coded like in the case of tuples.
The only difference is, that lists uses in their declaration the [..] parenthesis. So using lists the code
example of the section 2.14.1 can be coded like follows.
You can read somewhere, that tuples are much more faster than lists. This is surely not valid for every
problem. So it’s recommended to check the performance explicitly before you decide to use tuples or
lists.
The list object offers a wide set of methods. Some of them are discussed in the following table.
E. Baeck
2.14. DATA SEQUENCES Page 41
Now, how can we implement a stack with basic Python? We simply need a list instance with the two
functions append(), which implements the Push and pop() which implements the Pop of a stack.
10
If we save data on a stack, it’s called push data onto the stack. If we take data from the stack, it’s called pop data from the
stack.
8.5.2018
Page 42 Analysis of Structures - SS 15
A dictionary is a powerful and very general container, it’s also called map, because a key value is mapped
onto the pointer of the stored item. In Python an instance pointers is stored in a dictionary using an
arbitrary key strings. So a dictionary is like a list container with a more general access. Because the
dictionary commonly hashes the key information onto some smaller index lists, the dictionary commonly
has a better performance as a linked list container. The dictionary therefore is used in the abaqus class
library (we will discuss it later) to store named instances.
A dictionary can be created like a list using curled parenthesis. Each key-value pair is separated by a
comma. The key is separated from the value by a colon.
1 >>> myDict = {’first item’:1, ’second item’:2}
2 >>> print myDict[’second item’]
3 2
4 >>> beatles = {}
5 >>> beatles[’drums’] = ’Ringo’
6 >>> beatles[’bass’] = ’Paul’
7 >>> beatles[’vocal’] = ’John, Paul, George, Ringo’
8 >>> beatles[’guitar’] = ’George, John’
9 >>> print beatles
10 {’guitar’: ’George, John’, ’vocal’: ’John, Paul, George, Ringo’, ’bass’: ’Paul’,
11 ’drums’: ’Ringo’}
There are (at least) two distinguishable kinds of errors: syntax errors and exceptions.11
Syntax errors, also known as parsing errors, are perhaps the most common kind of complaint you get
while you are still learning Python.
1 >>> while True print ’Hello world’
2 File "<stdin>", line 1, in ?
3 while True print ’Hello world’
4 ˆ
5 SyntaxError: invalid syntax
The parser repeats the offending line and displays a little arrow pointing at the earliest point in the line
where the error was detected. The error is caused by (or at least detected at) the token preceding the
arrow: in the example, the error is detected at the keyword print, since a colon (’:’) is missing before it.
File name and line number are printed so you know where to look in case the input came from a script.
11
Parts of this section are taken from the Python 2.7 manual.
E. Baeck
2.15. ERROR HANDLING WITH EXCEPTIONS Page 43
2.15.2 Exceptions
Even if a statement or expression is syntactically correct, it may cause an error when an attempt is made
to execute it. Errors detected during execution are called exceptions and are not unconditionally fatal. We
will see how to handle them in the next section. Most exceptions are not handled by programs, however,
and result in error messages as shown below.
1 >>> 10 * (1/0)
2 Traceback (most recent call last):
3 File "<stdin>", line 1, in ?
4 ZeroDivisionError: integer division or modulo by zero
5 >>> 4 + spam*3
6 Traceback (most recent call last):
7 File "<stdin>", line 1, in ?
8 NameError: name ’spam’ is not defined
9 >>> ’2’ + 2
10 Traceback (most recent call last):
11 File "<stdin>", line 1, in ?
12 TypeError: cannot concatenate ’str’ and ’int’ objects
The last line of the error message indicates what happened. Exceptions come in different types, and
the type is printed as part of the message: the types in the example are ZeroDivisionError,
NameError and TypeError. The string printed as the exception type is the name of the built-in
exception that occurred. This is true for all built-in exceptions, but need not be true for user-defined
exceptions (although it is a useful convention). Standard exception names are built-in identifiers (not
reserved keywords).
The rest of the line provides detail based on the type of exception and what caused it.
The preceding part of the error message shows the context where the exception happened, in the form of
a stack traceback. In general it contains a stack traceback listing source lines; however, it will not display
lines read from standard input.
It is possible to write programs that handle selected exceptions. Look at the following example, which
asks the user for input until a valid integer has been entered, but allows the user to interrupt the program
(using Control-C or whatever the operating system supports); note that a user-generated interruption is
signalled by raising the KeyboardInterrupt exception.
1 >>> while True:
2 ... try:
3 ... x = int(raw_input("Please enter a number: "))
4 ... break
5 ... except ValueError:
6 ... print "Oops! That was no valid number. Try again..."
7 ...
• First, the try clause (the statement(s) between the try and except keywords) is executed.
• If no exception occurs, the except clause is skipped and execution of the try is finished.
8.5.2018
Page 44 Analysis of Structures - SS 15
• If an exception occurs during execution of the try clause, the rest of the clause is skipped. Then
if its type matches the exception named after the except keyword, the except clause is executed,
and then execution continues after the try.
• If an exception occurs which does not match the exception named in the except clause, it is passed
on to outer try; if no handler is found, it is an unhandled exception and execution stops with a
message as shown above.
A try may have more than one except clause, to specify handlers for different exceptions. At most
one handler will be executed. Handlers only handle exceptions that occur in the corresponding try
clause, not in other handlers of the same try. An except clause may name multiple exceptions as a
parenthesized tuple.
1 ... except (RuntimeError, TypeError, NameError):
2 ... pass
In the next example we open a file with the name ’input.dat’. We read one line and strip the leading and
trailing blanks. The result will then be converted to an integer. We know that this is not possible in every
case, so we want to handle possible errors by our error handler.
1 try:
2 f = open(’input.dat’) # let’s open then input file,
3 s = f.readline() # read the first line and
4 i = int(s.strip()) # strip the white spaces
5 except IOError as e: # catch the io-errors
6 print "I/O error(%d): %s" % (e.errno, e.strerror)
7 except ValueError: # catch conversion errors
8 print "Could not convert data to an integer."
9 except: # catch the rest
10 print "Unknown error!"
If we want to avoid runtime errors, we have to check our data base. In an classical approach, we have to
check the data, and break each activity jumping back to the origin of our call. Sometimes especial if the
calling hierarchy is extensive, it becomes an evil and tedious work to do this. On the other hand in most
modern languages we can use exception handlers to do this work for us. The only thing we have to do
is, to raise our own exception and check for it within an except clause.
The first listing 2.8 we call our square root function with a negative value.
1 import math
2
3 def mySqrt(x):
4 return math.sqrt(x)
5
6 print mySqrt(-2)
E. Baeck
2.16. RANDOM NUMBERS Page 45
2 File "C:\Python27\Lib\site-packages\Pythonwin\pywin\framework\scriptutils.py",
3 line 326, in RunScript
4 exec codeObject in __main__.__dict__
5 File "C:\UniDue\CM\Cm-AoS\AOS-BookOfExamples\Py\Code\ExceptionEx01.py", line 7,
6 in <module>
7 print Sqrt(-2)
8 File "C:\UniDue\CM\Cm-AoS\AOS-BookOfExamples\Py\Code\ExceptionEx01.py", line 4,
9 in mySqrt
10 return math.sqrt(x)
11 ValueError: math domain error
We see that obviously the function sqrt is not able to handle negative numbers.
In the next example we check the root’s value and raise an exception to break the function. This exception
itself is caught by the main program with an try clause.
1 import math
2
3 def mySqrt(x):
4 if x < 0.:
5 raise Exception("error: negative input value %e!" % x)
6 return math.sqrt(x)
7
8 try:
9 print mySqrt(-2)
10 except Exception as e:
11 print e
In listing 2.9 we see, that if negative values are passed, the function will raise an exception. Using the
Exception class we send a string information, which can be caught within the except clause. The
output of this version is given below.
1 error: negative input value -2.000000e+00!
We see, that the concept of an exception handling is a powerful feature to implement error checking.
Because a computer is system, which works systematically reproducible, a computer will not be able to
create real random numbers. If we start a program twice with exact the same input values, the result also
will be the same. But with a little trick, we can produce so called pseudo random numbers. If we use
the time as input for the initialization of our random number generator, we will be sure, that it will be
extremely improbable, to get twice the same random number set.
So every programing language has it’s own random number generator. Python offers us a build-in pack-
age, which is called random. Like in C the random number generator is to initialize with a function
seed(). This function uses the computer time information to make varying starting conditions.
The following example will discuss two features of the Python library.
• How can we use the random package to create random numbers or to create a random order of
lists, i.e. shuffle the list’s data.
8.5.2018
Page 46 Analysis of Structures - SS 15
• How can we create simple 2d diagram plots using the matplotlib package.
• At the beginning the lists xPos and yPos are filled with random numbers. This random x and y
values are interpreted as point coordinates. Two subsequent points are joint by a line.
• Within a second step the list’s element are sorted. The result is plotted again. The result is an
increasing function.
• Within the third step the sorted lists are shuffled by the random package. The random order of the
random numbers is plotted again.
Figure 2.8 shows the walk for random points (blue line), for sorted points (red line) and for shuffled
points (green line). The left figure shows the content of the created png file, the right figure shows the
plot within the viewers window.
Listing 2.10: Implementation a Kind of Random Walk visualized with two Lists of Random Numbers
9 numbers = []
10 for i in range(count):
11 r = lower + (upper-lower)*random.random()
12 numbers.append(r)
13 return numbers
14
E. Baeck
2.17. DATE, TIME AND TIMESPAN Page 47
20 # random positions
21 xPos = getRandomNumbers(L,U,xN) # ...in x-direction
22 yPos = getRandomNumbers(L,U,xN) # ...in y-direction
23
Date and time functions in common are very important and therefor Python supports this with a stan-
dard package datetime. Within this package you will find some very simple and powerful objects and
functions.
The package is loaded with the following statement. We load from datetime the subpackage datetime
and set the alias name time. The second line shows, how to get the actual time. The datetime object
contents from the left to the right the year, the month, the day, the hour, the minutes, the seconds and
the microseconds. Because the computer does not support microseconds but milliseconds the measured
milliseconds are multiplied with the factor 1000.
1 >>> from datetime import datetime as time
2 >>> time.now()
3 datetime.datetime(2010, 11, 4, 19, 25, 33, 15000)
To implement some performance checking code it is very useful to have a timespan, which is the dif-
ference of two datetime objects. The timespan object is called timedelta and is as well an object of the
datetime package.
8.5.2018
Page 48 Analysis of Structures - SS 15
If we now want to check the performance of a code snippet, we will implement the following code.
First we have to import the datetime package. Then we get the actual time and assign this object to the
variable t1. Then the code to check follows. Within a last step we again create a datetime object calling
the time.now() function and assigning the object to the variable t2. If we subtract t1 from t2 we
will get a timedelta object. The timedelta objects contents the number of days, the number of seconds
and the number of microseconds of the time difference.
1 from datetime import datetime as time
2 t1 = time.now()
3 ... our code snippet ...
4 t2 = time.now()
5 t3 = t2 -t1
6 print t3
7 >>> datetime.timedelta(0, 12, 906000)
If we want to have the time difference in seconds, we have to write a little function, which adds all this
time parts in the unit second. If we suppose, that T is a valid timedelta object, we extract the seconds with
the seconds attribute and assign it to our seconds variable. The next part handles the microseconds.
We divide them by 106 and add the part to the seconds variable. The last part calculates the seconds of
the given hours and add this value to our second variable. The value is returned to the caller.
1 def getTimeSpanInSeconds(T):
2 secs = float(T.seconds)
3 secs += float(T.microseconds)/1.e6
4 secs += float(t.days)*24.*60.*60.
5 return secs
One very important application of the timedelta object is the measurement of a program’s performance.
The next example shows how to investigate the performance of the creation of a tuple and the creation of
a list. Here we apply the above discussed function getTimeSpanInSeconds.
11
E. Baeck
2.18. WORKING WITH FILES Page 49
The console output on a one year old double processor notebook is given below. You see that it is very
wasteful to create a tuple with a lot of items concatenating them with a += operator. On the other hand a
list with the some number of items is created in no time. And the conversion of a list into a tuple costs
nothing. So we can resume the the creation of a very large tuple should be done by creating a list and
converting it into a tuple.
1 c:\CM\Cm-AoS\WS1011\Python>Timecheck1.py
2 Creation of a tuple with 100000 items: 33.297s
3 Creation of a list with 100000 items: 0.063s
4 Create tuple from list: 0.000s
A file is a sequence of bytes written to an external media like a hard disk, a CD or an USB stick. A file’s
bytes are indexed with an integer. So the the fist byte of a file has the index 0 and the second byte the
index 1 and so on. A text file is structured with a line break character \n. If a text line should be read,
the io12 system reads all the bytes up to the next line break.
Python as a lot of functions which are able to handle every situation concerning files. So files can be
created. We can read data from a file or write data into a file. We can close a file. We can delete a file or
change it’s permissions.
Within Python a file is an object an has a lot of attributes and methods (see also the next section). The
access to a file is initialized with the file constructor. The file constructor needs the name of the file and
the type of access. The file access type is like C’s access type of the function fopen13 . The type ’r’ is
used to read from a file, the type ’w’ is used to create a new file for writing. An old still existing file
will be deleted. The type ’a’ is used to write appending to an existing or a new file. If we want to read
from and write into a file the type ’w+’ can be used.
12
io means input output.
13
The function fopen is C’s classical function to open a file. The return will be a pointer to a FILE structure.
8.5.2018
Page 50 Analysis of Structures - SS 15
1 f = file(<filename>,<access-type>)
2 ...
3 ... example ...
4 ...
5 f = file("myfile.txt", "w")
The file method write writes a stream of bytes into a file. In contrast to the print function the write method
adds no carriage return to the file. If a line of text should be written, the text should be closed with an \n
character.
1 #> f.write(<byte-stream>)
2 #> ...
3 #> ... example ...
4 #> ...
5 f.write("This is my first line\n")
A frequently problem is parsing an input file for some control data. This we can do with a statement
which reads the entire file into a list container using the method readlines. If we have read this lines then
we can iterate this container using the for statement. Doing this we will get line by line.
A line is a string which is terminated by a carriage return character. This string we can split up into
pieces using white spaces (blanks and tabs) as separators.
E. Baeck
2.18. WORKING WITH FILES Page 51
In our example we want to read and analyze the input file data.in (see listing 2.13).
1 # this is a comment
2 # format is key - value like
3 H 100.
4 W 10.
If we run the script 2.12 we will get the console output 2.14. In line 1 we can see, that readlines will
create a list container (see square brackets).
8.5.2018
Page 52 Analysis of Structures - SS 15
2.18.5 A Logger-Function
In many cases it is very useful to have logging, to know, what is going on in an application. A logging
function has to flush the data after every write event to the disk to avoid the loss of data. If a write event
is executed first the data is written into a buffer memory. So if the program is crashing before the data
are written physically to the disk, the data are lost and the effect of such a log is rather suboptimal. One
very secure kind of logging is, to open a file for writing in append mode, write the desired data to the file
and close the file after having written the data. This is secure but the performance is low.
In the next example an implementation of a logging function is given. Later we will implement this
function as part of a logger class.
E. Baeck
2.19. OOP WITH CLASSES Page 53
An instance of a class, that is the realization of the class in memory, is created simply by assigning the
class’s name followed by the constructors parameter list to a symbolic name, which than is the pointer or
the reference to this instance. Within the class the self pointer to the actual instance is called self. To
access member attributes or methods of a class the dot notation is used, i.e. <instance>.<member>.
We can remove an instance of a class by calling the del operator (del example). The references
to an instance are handled by the python runtime system. If an instance has lost all it’s references, the
instance is removed from the memory.16
UML structure diagrams of the emphasize the things that must be present in the system being modeled.
Since structure diagrams represent the structure they are used extensively in documenting the architec-
ture of software systems. In our description of the examples we want to implement we use the Class
Diagram which describes the structure of a system by showing the system’s classes, their attributes, and
the relationships among the classes.
A UML note diagram (see figure 2.9) consists of a stylized note sheet which is filled with some informa-
tion.
MyClass
this is my 1st class
Attribute1 A UML note diagram (see figure 2.10) will be assigned
Attribute2 to an other component of the diagram scene with a sim-
ple line.
Method1
Method2
14
Object orientated Programming is often used with the abbreviation OOP.
15
The Unified Modeling Language includes a set of graphic notation techniques to create visual models of software-intensive
systems. The Unified Modeling Language is an international standard see [4], UML 2.3 was formally released in May 2010.
16
This is also called Garbage Collector. In contrast to this in poor C or C++ an once allocated object has to be removed
explicitly from the memory to avoid so called memory leaks, this are blocked parts of the applications memory, which remain
unaccessible until the application is closed.
8.5.2018
Page 54 Analysis of Structures - SS 15
Figure 2.11 shows how to draw diagrams for inheriting Base Class Derived Class
classes. An arrow with a white filled arrowhead points
from the inheriting class, the special class, to the inher- − attributeB1 + attributeS1
ited class, the base class. The attributes and the methods − attributeB2 − attributeS2
of the Base class are now available in the name space of
− methodB1 + methodS1
the inheriting class, i.e. the derived class now has the at-
+ methodB2 + methodS2
tributes attributB1, attributB2, attributS1 and
attributS2. Figure 2.11: A UML Inheritance Diagram
The prefixes + and − describe the access permissions. + items are accessible from outside. In C++
they get the public attribute. − items are not accessible from outside, only methods of their class are
allowed to access. In C++ they get the private attribute.
There are to different class items, an item which is related only to a class Base Class
and an item which is related to an instance. An instance related item needs
an instance. So if an instance is created the item is available with this − attributeB1
instance pointer. Without an instance the item is not available. So an − attributeB2
instance related item can have an arbitrary multiplicity, so every instance
− methodB1
has it’s own item. This item is listed without an underlining.
+ methodB2
On the other hand there are items which are related to the class. This item
Figure 2.12: Item Types
are accessed using the class name as a prefix and not the instance name.
A class item one once exists in the application. A class related item is listed in the UML class diagram
with an underlining.
Class 1
Figure 2.13 shows a aggregation and a composition. An
List A aggregation is drawn by a white filled rhombus. An com-
List B position is drawn by a black filled rhombus. Aggregation
and compositions describe a container or a list of several
Method 1
instances of an object, which are members of a main class.
If for example a profile consists of several parts, the parts
can be described as an composition, if a part only exists
3..* sorted 1 random
within a profile. If a part exists also without a profile, the
Class A Class B parts are described within the profile with an aggregation.
Attribute A1 Attribute B1 At the ends of the connecting lines the multiplicities are
Attribute A2 Attribute B2
noted. The multiplicity gives the range of referenced in-
stances in the form from..to. For the Class A we have 2
Method A Method B up to infinite instances in an composition, therefor at the
end of the line we can not have a multiplicity of zero. In
Figure 2.13: A UML Diagram for a Composi-
tion and an Aggregation our example we have exactly one instance of the class 1.
On the other hand Class B is referred to Class 1 within an
aggregation. In our example on instance of Class B can be
reverenced by an undefined number of instances of Class 1. This is shown by the * icon. On the other
hand the class 1 references at least on instance of the Class B. Otherwise the number of references is
arbitrary. This is also shown by the * icon.
E. Baeck
2.19. OOP WITH CLASSES Page 55
The constructor of a class is called if an instance is created. A constructor is a function, i.e. method of
a class, having a fixed name. The constructor defines the interface to the class, if an instance should be
created.
The following code shows the constructor of class ClassZ and how to create it’s instance. The name
of the constructor is __init__. The leading two underscores set the constructor to private, i.e. this
method is hidden and is not allowed to call from outside. We also should notice, that an instance reference
in Python is passed with the key self. This parameter, the first in the implementation, is not explicitly
passed (see line 9). Only the the real parameters should be passed in the call. A further thing to mention
is, that instance attributes are only created, if an assignment is done.17
1 class ClassZ(ClassX, ClassY):
2
3 def __init__(self,par1,par2):
4 self.attributeZ1 = par1
5 self.__attributeZ1 = par2
6
7 ..
8
9 c = ClassZ(1,2)
17
In a compiled language like C++ or FORTRAN a variable, an attribute or a method are created in compile time, they are
available already at start up.
8.5.2018
Page 56 Analysis of Structures - SS 15
The destructor of a class is called if an instance is deleted with the del command, which means is freed
from the memory. The destructor is a functions, i.e. method of a class, having a fixed name.
The following code shows the destructor of class ClassZ. The name of the destructor is __del__. The
leading two underscores set the destructor to private, i.e. this method is hidden and is not allowed to call
from outside. We also should notice, that an instance reference in Python is passed with the key self.
The destructor only has one parameter the instance reference. The example shows like before how we
create an instance of the class ClassZ and how to free it. If we free this instance, the instance’s method
__del__ is executed and gives us a goodby.
1 class ClassZ(ClassX, ClassY):
2
3 ...
4
5 def __del__(self):
6 print "goodby!"
7
8 ..
9
10 c = ClassZ(1,2)
11 del c
E. Baeck
2.19. OOP WITH CLASSES Page 57
In section 2.17 we have discussed a little program which implements a time checker using a stack con-
tainer. We can implement this problem in a much more clearer version, if we do it in terms of the OOP
approach. The class TimeCheck, which is introduced, encapsulates the time stack list and the log files
name as attributes and the following methods.
• set reads the actual time with the datetime.now() and pushes it onto the time stack.
• get reads the actual time with the datetime.now(), pops the the last time object from the stack and
calculates the timespan. The timespan is optionally printed into the console window or into a log
file.
• getTime calculates the seconds in floats form the passed timedelta object.
The main program, which is used to discuss the class follows the steps of the classical implementation
of the problem discussed in section 2.17. We first create an empty tuple and an empty list. Than we
create the TimeCheck instance18 simple by assigning it’s name to a variable (s = TimeCheck()). To
push a time object onto the stack, we call the class’s member function Set. So, if we want to check the
performance of a code, we first call the Set method and after having executed the code, we call the Get
method. The Get method will print the comment and will return the used seconds of execution time in
floats. The simplest kind of an implementation is the implementation in the file of the main program.
This you can see in the following example.
TimeCheck
+ self. log: name of the log file The class TimeCheck contents all the data and
+ self. stack: stack list functions to use a time stack and to get the
time-span information in a proper float format.
+ self. init (..): contructor
The class is able to present a formated output
+ self.set(..): push a time of the measured time-spans.
+ self.getTime(..): calculate seconds
+ self.get(..): pop a time
18
A physical created object in memory of a class is called instance of a class.
8.5.2018
Page 58 Analysis of Structures - SS 15
1 ’’’
2 Class to investigate the timespan, to measure the performance
3 by implementing a time stack container
4 ’’’
5 # - module - member alias
6 from datetime import datetime as time # we need the datetime package
7
10 # constructor
11 def __init__(self,log = "timestack.log"):
12 self._stack = [] # empty list
13 self._log = log # set the logfile’s name
14
E. Baeck
2.19. OOP WITH CLASSES Page 59
55
If we run the program, we see that two time stamps are indented with one dot. This timestamps are set
for inner performance measurements, that is the time-stamp for the creation of the tuple and after that
the time-stamp for the the creation of the list. The last time-stamp shows the total execution time and is
created by the first push, i.e. the first Set call and the last pop, i.e. the last Get call.
1 >> Start..
2 . 8.282 : Creating 50000 item tuple.
3 . 0.016 : Creating 50000 item list.
4 8.329 : total time
8.5.2018
Page 60 Analysis of Structures - SS 15
E. Baeck
3
Python Projects
We have discussed the newton’s scheme in section 2.10. Within this section the project’s code will be
extended by plot features. The function and it’s derivative as well as the path of iteration will be plotted
using the pylab package.
2. The function getFunctionValues creates a list of the function values for the plot routine.
3. The function getFunctionDerivativeValues creates a list of the function’ derivative values for the
plot routine.
4. The function newton will be extended by two lists, which should store the values of the iteration
path. After each iteration step, the x-value and it’s function value are stored for later drawings.
61
Page 62 Analysis of Structures - SS 15
A disadvantage of the first implementation in section 2.13.2 is, that the algorithm will fail, if a vanishing
slope is found. With a simple work around we can solve this problem. We simple step aside as long as a
minimum slope value is reached. The flow chart is given in figure 3.1.
Start
Initializing:
x = x0 ; i = 0;
yes
i ≥ imax NO ROOT! Stop
no
F x = f (x)
yes
|F x| ≤ ROOT: x Stop
no
F s = f 0 (x)
yes x = x+∆
|F s| ≤
i = i+1
no
Fx
x = x− Fs
i = i+1
E. Baeck
3.1. NEWTON, STEP2 Page 63
13 x = float(x)
14 return (f(x+0.5*h) - f(x-0.5*h))/h
15
30 i = 0 # iteration counter
31 while True:
32
51 if abs(f1) < e:
52 x1 += 1.e2*h # little step aside
53 i += 1 # avoid dying with a vanishing slope
54 continue
55
8.5.2018
Page 64 Analysis of Structures - SS 15
69 def getFunctionValues(xL,f):
70 yL = []
71 for x in xL:
72 y = f(x)
73 yL.append(y) # yL += [y]
74
75 return yL
76
84 return yL
85
E. Baeck
3.1. NEWTON, STEP2 Page 65
After the output lists are created the lists are passed to the plot post-processor by the plot method of
PyLab. After enabling the grid the plot data are written in a graphic file and are visualized in the PyLab
viewer application.
Figure 3.2 shows the iteration path for the equation f (x) = x2 − 1 with an starting value of 4 with red
dots.
If we would start our calculation with a starting value of 0, we know that the slope will vanish. If we
now step aside with the precision of our numerical derivative, we will get the following iteration path.
1 x0 = 0.000000
2 x = 1.000000
3 f(x) = 0.000000
4 f’(x) = 2.000000
5 i = 18
6 --------------x -----------f(x) ----------f’(x)
7 0.000000e+00 -1.000000e+00 0.000000e+00
8 1.000000e-04 -1.000000e+00 2.000000e-04
9 5.000000e+03 2.500000e+07 1.000000e+04
10 2.500001e+03 6.250002e+06 5.000003e+03
11 1.250001e+03 1.562501e+06 2.500002e+03
12 6.250008e+02 3.906250e+05 1.250002e+03
8.5.2018
Page 66 Analysis of Structures - SS 15
We see that due to the very small slope, the resulting jump in the iteration is very large, so that we need
some iterations more to get the root. If we would do this on a very flat function like f (x) = x1 0 − 1, we
have to count the steps, to avoid the programs hanging. The function is as flat that the number of small
steps to get out of the trap will increase to a nearly infinite number.
Figure 3.2 shows the iteration path for the equation f (x) = x2 − 1 with an starting value of 0 with red
dots.
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 67
In this section we will implement a class hierarchy to model a profile’s data. We will implement logging
into file and screen in a common base class and we will implement the thin walled approach to analyze
and calculate the profile’s section properties.
Applying the Thin Walled Approximation every part of a section will be approximated by a line with a
given thickness. This approach is similar to the approach modeling a three dimensional shell structure.
Hereby we use shell elements, i.e. faces, with a given thickness. The lines like the shell elements in FE
will connect nodes or points.
So if we want to build up a calculation model for our thin-walled section, we need something like lines
and points. Lines are called Elments and Points are called Nodes like in the case of programs. In our
case we introduce two classes.
• The class Node describes the contour point of elements. In our case we have the end points of
lines in two dimensions.
• The class Element describes the connection between nodes. In our case we connect points with
lines so that we have to specify the thickness of the line, ie. the connection.
Further we introduce a class Base, which should content all common features. A general profile then
will be described by the class Profile. This class can therefore be considered as a container for our points
and lines as well as the class which should perform all calculations. To show the power of inheritance we
introduce a derived profile class, which is called UProfile. This class will describe all U-profiles with
their geometric parameters. Based on our class Profile this class will be able to calculate all section
values based on the given parameter set. All details, i.e. points and lines are encapsulated in it’s base
class.
If we want to use the code of an existing class within a new class, we can inherit this old class and use
it as a base class. That means, that the new class contents also the attributes and the methods of the old
one. A base class is used in the class statement as an argument. A class can inherit more than one class.
In our case everything is derived from our general base class called Base.
The class Base should content logging for all classes. This class should also be able to count all cre-
ated instances of the developed application. The output method for all classes should be the method
AppendLog, i.e. this method will be inherited by all classes of our project. The classes UML diagram
is given in figure 3.4.
The class Base counts the instances using the global class attribute __count. A common logging
method is implemented. So the name of the log file is implemented as a class method (not an instance
method) __log. The method appendLog is implemented as a general logging function. The actual
time is called an copied as heading for our logging comment. Then the completed logging text is written
into the log file and into the screen.
8.5.2018
Page 68 Analysis of Structures - SS 15
Base
− log: global log file name The class Base contents common
− count: global instance counter features which are used in every
class.
− self. init (..): constructor
+ self.appendLog(..): write to log
1 ’’’
2 the Base class of all TWA-classes
3 ’’’
4 # import some packages
5 # |package
6 # | | select the item to import
7 # | | | alias name
8 from datetime import datetime as time
9
10 class Base:
11 __log = "profiles.log" # class attribut, type private
12 __count = 0 # class attribut, instance counter
13
14 # construtor
15 # |instance pointer
16 # | |optional parameter
17 def __init__(self,log = ""):
18 Base.__count += 1 # increment the counter
19 if len(log) > 0: Base.__log = log # set a new log-file name
20
32 # use the file object to print with the append mode "a"
33 f = file(Base.__log,"a")
34 f.write(textout+"\n") # write text
35
36 print textout
37
38 # destructor
39 def __del__(self):
40 self.appendLog("instance %d deleted" % Base.__count)
41 Base.__count -= 1 # decrement the counter
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 69
The class Node only has the attributes of the points number and it’s coordinates. The coordinates are
stored within a list. If we do this, we simply can extend this object to a three dimensional application.
Besides the constructor we will implement a method list, which should be able to print the instances
data to a given output stream. This method will use our method appendLog of the base class. The
classes UML diagram is given in figure 3.5.
Base
Will provide appendLog
Node
1 __author__ = ’baeck’
2
3 # forced reload
4 import Base
5 reload(Base)
6
7 # module item
8 from Base import Base
9
13 # constructor
14 # self pointer
15 # number and the coordinates
16 def __init__(self,no,x,y):
17
21 try:
22 self._no = int(no)
23 self._x = [float(x),float(y)]
24 except:
25 raise "*** error: invalid input!"
26
27 # destructor
8.5.2018
Page 70 Analysis of Structures - SS 15
28 def __del__(self):
29 pass
30
In our testing environment we simple import the Node module. Than we create a Node instance and list
it’s data. After that we delete the instance and we try to print it again.
1 ’’’
2 checking the Node class
3 ’’’
4 import Node # we have to be sure
5 reload(Node) # that we check the current file
6
The output of our test application is given in the following code. We see, that the Base class constructor
shows, that a new instance is created. The next line shows the output of Node’s list method followed
by the simple instance print, which shows the address of the instance. Than the instance is explicitly
deleted, so that the destructor of the Base class shows that one instance is deleted. Because the address
of the instance after deleting is invalid, the program will crash with a trace back message. The line (line
15) is given and the message shows us, that at this moment there is no valid variable called p.
1 15.49.12 |>> instance 1 created!
2 15.49.12 | point 3, y = 1.000, z = 2.000
3 <Node.Node instance at 0x031AE300>
4 15.49.12 |instance 1 deleted
5 Traceback (most recent call last):
6 File "C:\Python27\Lib\site-packages\Pythonwin\pywin\framework\scriptutils.py",
7 line 326, in RunScript
8 exec codeObject in __main__.__dict__
9 File "C:\UniDue\CM\Cm-AoS\AOS-BookOfExamples\Py\Code\Profiles\NodeApp.py",
10 line 15, in <module>
11 print p # try to print it again
12 NameError: name ’p’ is not defined
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 71
The class Element will describe the connection between points and will describe further the type of
connection. In the case of a line we will have the line’s thickness. Because in our case the properties of
the profile, i.e. it’s area and moments, are given by the sum over the element’s contribution (see section
B), we put the code to calculate this properties into the element’s class. If we do so, the element must
know everything about it’s points, i.e. the numbers of the points are not sufficient to have success. So
we store the point’s instance pointers and not there number in our element. The classes UML diagram is
given in figure 3.6.
The element can be considered as a container for Node instance pointers too. This is shown within the
diagram using the composition link to the class Node. The cardinality in our case is exactly two. If we
would introduce faces too for the thick-walled case, the cardinality can also be greater then two.
Base
Element
2..*
8.5.2018
Page 72 Analysis of Structures - SS 15
1 __author__ = ’baeck’
2 ’’’
3 implementation of an element class
4 ’’’
5 import Base
6 reload(Base)
7
8 # module item
9 from Base import Base
10
14 # constructor
15 def __init__(self,no,node1,node2,t):
16
17 Base.__init__(self)
18
19 self._no = no
20 self._n = [node1,node2]
21 self._t = t
22
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 73
In our testing environment we simple import the Element as well as the Point module. Than we create
two Node instances, which will describe the end points of our line. Then the Element instance is
created, passing the two Node instance pointer and the lines thickness. After that we list the element’s
data and delete it.
1 ’’’
2 check the Element class
3 ’’’
4 import Element # do this if you want to sure
5 reload(Element) # that the module file is the currend one
6
10 h = 200.
11 t = 5. # thickness
12
23 # delete instances
24 del n1
25 del n2
26 del e1
The following output shows, that 3 instances (2 nodes and 1 element) are created. We see the element’s
data, i.e. the node numbers (3,2) and the thickness (5.0). The length and die area are calculated by the
8.5.2018
Page 74 Analysis of Structures - SS 15
The element’s length obviously is 200 and the area 1000. If we apply the well known formula for the
3 3
moment of inertia of an rectangle I = h12·w = 20012 ·5 = 3.33 · 106 we get the value in the listing. So it
seems to be ok.
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 75
So if we want to develop a software, which is able to calculate the profile’s section properties like it’s
area, moment of inertia and so on, we can consequently split up the problem in general and specific
parts. So we start with the data and the functions of a general object. This data is collected in a class
which we call Base. So if we want to describe a wide range of profile types, then we should think about
the profile’s common features. Every profile has a name and therefore this name is a common feature.
This common features are collected in a general profile class which is called Profile. If we want to
handle a specific profile type given by a set of parameters like an U-profile ore a tube profile, we collect
the specific type dependent features in the classes UProfile and TubeProfile, which are obviously the
parameters describing the profile’s geometry.
The class Profile now contents common profile features. One of them is the profile’s name. Note,
if we inherit a class from a base class, we have to call the base class’s constructor method. Every
attribute and every method of the base class is now available. A second feature of the Profile class is
the implementation of the thin walled model. Therefore we introduce an Element container using the
AList class. With a specific method we insert an Element instance into the container. To calculate the
section values of the created thin walled model we introduce some methods, which calculate the global
section values summing up all element values and transforming them into the desired coordinate system.
At least we introduce a little viewing method, which should create a png picture file of the profile and
should optionally start the pylab viewer tool. To be sure, that the environment supports the Tkinter
package1 , which is used by the viewer, we import the package using a try: ... except: handler.
At the end of the view method we should close the plot, to avoid a memory effect.
Profile
A U-profile is described within the frame of the TWA by it’s height and width as well as by the thicknesses
of it’s web and flange. So we need 4 floats to do this. It’s UML diagram is given in figure 3.8.
1
We will see later trying to apply our package Profiles in the frame of the Abaqus scripting, that we will get problems,
because the Abaqus environment is not developed with Tkinter.
8.5.2018
Page 76 Analysis of Structures - SS 15
UProfile
+ self. h: height
The class UProfile contents the
+ self. w: with special features of an U-Profile,
+ self. s: web thickness i.e. the geometric parameters.
+ self. t: flange thickness The class will be inherit the Pro-
file class and will have the feature
− self. init (..): constructor to create this profile with an U
+ self.list(..): list profiles values geometry.
+ self.check(): check input values
+ self.create(..): create thin walled model
A tube-profile is described within the frame of the TWA by it’s diameter and it’s thickness. So we need
only 2 floats to do this. It’s UML diagram is given in figure 3.9.
TubeProfile
+ self. d: diameter
The class TubeProfile contents
+ self. t: thickness
the special features of a Tube-
− self. init (..): constructor Profile, especially the geometric
+ self.list(..): list profiles values parameters
To hold the desired Element instances we implement a slightly modified list class, which should
work like an array with a well defined index access (see section 3.2.7). If we would use a standard list
class, we would get problems if we want to insert an object at a position outside the list range. Then a
standard list object simply appends this object as a new item at the tail of the list and we would loose the
correct index position. So we implement a new index save Add method, which checks the list length and
if necessary enlarges the list up to the desired index position.
3 __author__ = ’baeck’
4 ’’’
5 Profile class to calculate section values
6 with the thinwalled approximation
7 ’’’
8
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 77
12 class Profile(Base):
13
14 # constructor
15 def __init__(self,name):
16
17 Base.__init__(self)
18
22 # result data
23 self._a = 0.
24 self._s = [0.,0.] # static moments
25 self._e = [0.,0.] # center of mass coordinates
26 self._iu = [0.,0.,0.] # moment of intertia in user coordinates
27 self._ic = [0.,0.,0.] # moment of intertia in center of mass coordinates
28 self._ip = [0.,0.] # moment of intertia in principal coordinates
29 self._alp = 0. # rotation angle
30
46 # area
47 self._a += e.getA()
48
49 # static moment
50 for i in range(2): # [0],[1]
51 self._s[i] += e.getS(i)
52
53 # moment of inertia
54 for i in range(3):
55 self._iu[i] += e.getI(i)
56
8.5.2018
Page 78 Analysis of Structures - SS 15
68 return (self._a,self._s,self._ip,self._alp)
69
114 try:
115 import pylab
116 except:
117 self.appendLog("error: pylab not intalled!")
118 return
119
120
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 79
In our implementation of the Profile class we want to work with lists giving an array like feeling, i.e.
in every case an insertion with a given index has to be like an assignment to an array slot. If we now use
Pythons buildin list class, we will see, that if the index is greater than the upper-bound, the item to be
inserted will be appended. If so, we will loose the strict array behavior of our container. The solution is
very simple. We take the build-in list class and derive our own list object called AList.
The only thing we have to add to the build-in list will be an index save add method. On the other
hand it would be very comfortable, if we implement a list method, which is able to print every thing
inside the container in it’s desired format. The implementation of the last is very simple due to the
polymorphism strategy of OOP, i.e. an objects list method can be called without implementing a case
like filtering. This assignment is done automatically, because the general list method of an object is
projected onto the specific of the object. So every object will have it’s own list method. In our case
we have a Node and an Element object. Both of them, we have seen, have their own list method,
which then automatically is called.
8.5.2018
Page 80 Analysis of Structures - SS 15
AList
The class AList is based on the
python build-in list class. The
− self. init (..): constructor
Add method adds an object with a
+ self.add(..): Add by index given index value.
+ self.list(..): print instance’s data
1 __author__ = ’baeck’
2
3 ’’’
4 extends the python’s buildin class List
5 to get a perfect array feeling
6 ’’’
7
10 class AList(Base,list):
11
12 # constructor
13 def __init__(self):
14 Base.__init__(self)
15
23 if no > ubound:
24 for i in range(ubound+1,no+1):
25 self += [None,]
26
27 # store it!
28 self[no] = obj
29
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 81
37 try:
38 obj.list()
39 except:
40 self.appendLog("object %d is unprintable" % lobj)
41 # pass
42
43 lobj += 1
In line 6 we can see, that the AList has two base classes Base and list. The features of both classes
are inherited by our new one. Base is used to print and list is used to store the instance pointers.
In line 15 we see the new method add. If the index is less than the list’s length a general list add is done.
If not, we first enlarge the list up to the needed index value and then call the standard function. If we
do so, the list also can have wholes inside, i.e. None pointers. So we have to be careful with the array
access.
In line 27 we call the list method of every list index. To avoid crashing we simple make the list access
a save access by putting it into a try-except environment.
The Profile class can be considered as a container class for the Element instances. The cardinality is
one and greater. One we would have for a flat steel, two for an L profile and three for a U profile. The
UML diagram is given in figure 3.11.
1 1..*
To test the Profile class we implement a simple main program which creates the points of a TWA
based approximation of the unsymmetric L-profile L 100x50x6. The plates of the L have the length 100
and 50 mm. The thickness of the L is 5 mm.
1 ’’’
2 check the Profile class
3 3
4 | :2
5 :1 |
6 1---2
7 ’’’
8 import Profile
9 reload(Profile)
10
8.5.2018
Page 82 Analysis of Structures - SS 15
18 h = 100.
19 w = 50.
20 t = 6.
21
22 # create Noints
23 n1 = Node(1, -w,t/2.)
24 n2 = Node(2,-t/2.,t/2.)
25 n3 = Node(3,-t/2.,h)
26
27 # create elements
28 e1 = Element(1,n1,n2,t)
29 e2 = Element(2,n2,n3,t)
30
The application will give us the following output. We see, that the Profile’s list will print the name
and the section values of the total profile. Then we see that the list method is calling the list method
of the points and elements too. If an index instance is not available, the list method of the AList
will give a hint. In this case there is no element with number 0, therefore we get the message, that in this
slot there is no object found. The profile’s area is given in the standard profile table with 8.73 cm2 . The
deviation comes from the neglected filets.
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 83
2
Note, that the viewer of the used version is very sensible for multiple calls. So if you want to restart the program, you
should first close an open viewer instance. If not, the program will hang.
8.5.2018
Page 84 Analysis of Structures - SS 15
Figure 3.13 shows the UML diagram of the UProfile class. The parameters we pass to the classes
constructor are it’s name, the height, the width and the thicknesses of web and flange.
UProfile
+ self. h: height
The class UProfile contents the
+ self. w: with special features of an U-Profile,
+ self. s: web thickness i.e. the geometric parameters.
+ self. t: flange thickness The class will be inherit the Pro-
file class and will have the feature
− self. init (..): constructor to create this profile with an U
+ self.list(..): list profiles values geometry.
+ self.check(): check input values
+ self.create(..): create thin walled model
The implementation of the class UProfile is given in listing 3.10. The method create creates the
profile’s Node and Element instances. Before the geometry data is created the input parameters of the
U geometry should be checked. To cancel further activities, the simplest solution is to raise an exception
to break the execution.
1 ’’’
2 Implementaion of a UProfile class
3 ’’’
4 from Profile import Profile
5 from Node import Node
6 from Element import Element
7
8 class UProfile(Profile):
9
10 def __init__(self,name,h,w,s,t):
11
12 Profile.__init__(self,name)
13
14 self._h = h # height
15 self._w = w # width
16 self._s = s # web thickness
17 self._t = t # flansch thickness
18
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 85
42 hs = (self._h - self._t)/2.
43 ws = self._w - self._s/2.
44
To test the UProfile class we implement a simple main program, which passes the name and the
parameters of a U-geometry to the UProfile constructor. Then the data of the instance is printed. In
our example we calculate the values of an U80.
8.5.2018
Page 86 Analysis of Structures - SS 15
1 ’’’
2 check the UProfile class
3 ’’’
4 import UProfile
5 reload(UProfile)
6
The following lines show the output of the test application. The exact value of the U profile’s area is
11 cm2 . Note that we have to put the constructor call into a try-except frame to catch the exception.
1 >> UProfileApp: check the profile class
2 19.57.13 |Name.................: U80
3 19.57.13 | area...............: 11.0400 cmˆ2
4 19.57.13 | center of mass.....: 12.78 0.00 mm
5 19.57.13 | 1st moments.....: 0.00 14.11 cmˆ3
6 19.57.13 | 2nd moments ucs.: 105.75 39.51 0.00 cmˆ4
7 19.57.13 | 2nd moments scs.: 105.75 21.47 0.00 cmˆ4
8 19.57.13 | 2nd moments mcs.: 105.75 21.47 cmˆ4
9 19.57.13 | rotation angle..: 0.00 deg, tan(a) = 0.000
10 19.57.13 | element 1, A= 1, B= 2, t= 6.000 L= 72.000 A= 432.000
11 19.57.13 | center............: 0.000 0.000
12 19.57.13 | static moments....: 0.000e+00 0.000e+00
13 19.57.13 | moments of inertia: 1.866e+05 0.000e+00 0.000e+00
14 19.57.13 | node 1, y = 0.000, z = 36.000
15 19.57.13 | node 2, y = 0.000, z = -36.000
16 19.57.13 | element 2, A= 1, B= 3, t= 8.000 L= 42.000 A= 336.000
17 19.57.13 | center............: 21.000 36.000
18 19.57.13 | static moments....: 1.210e+04 7.056e+03
19 19.57.13 | moments of inertia: 4.355e+05 1.976e+05 2.540e+05
20 19.57.13 | node 1, y = 0.000, z = 36.000
21 19.57.13 | node 3, y = 42.000, z = 36.000
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 87
If we want to develop reusable code, it’s recommended to create a separate file for every class and put
them into a package. A package is a folder with the package’s name and a file called __init__.py.
If the __init__.py file is not found within the folder, the folder is not interpreted as a package and
the software components of the package can not be loaded. So we introduce a folder called Profile.
To initialize a package we have to create a file named __init__.py in this folder. If the package is
loaded, the __init__.py is executed. All our class files we put into this package folder.
If we implement a new class within the Profile package, we only have to import the module base, i.e.
the file Base.py. From this module we import the class Base. So we can write the import statement as
follows.3
1 from Base import Base # inherit from the Base
If we want to use a class from a package, we have to import it with the following statement.
1 from <package>.<module> import <class> as <locale name / alias name>
3
Note, that the file names are case sensitive although you may work on Windows plattform.
8.5.2018
Page 88 Analysis of Structures - SS 15
As an example we use the application for testing a U-profile (see listing 3.11). We move the file on folder
up, so that all our used class files are living in the subfolder Profile.4
The implementation of the testing environment using the package Profile is given in listing 3.13.
1 ’’’
2 check the UProfile class
3 ’’’
4 import Profile.UProfile # import total module
5 reload(Profile.UProfile) # reload total module
6 # make sure that’s the current
7 from Profile.UProfile import UProfile # import from a package
8 # from here on every thing is the same...
9 print ">> UProfileApp: check the profile class"
10 try:
11 # name h w s t
12 p = UProfile("U80",80,45, 6, 8)
13
To implement a simple profile data base for arbitrary profile instances, we can simply use the Python
buildin object dict 5 and extend it by inheritance with a specific list method (see figure 3.16). The list
iterates the dictionary getting the keys of the stored instances. With the given key we get the instance
pointer from the dictionary. Then we can use the mechanism of the polymorphism and call the instances
specific list method. If there is an error occurring, the try/except error handler will do his job and
executes the except branch code. So we can avoid program crashing due to invalid ore missing pointers.
1 from Base import Base # the ProfDB class should inherit the Base class
2
7 def __init__(self):
8 Base.__init__(self) # call the Base constructor
9
4
Note, if we do so, we also can move the total folder Profile into Pythons folder Lib/site-packages.
5
A dictionary is used to store instance pointers with an arbitrary access key.
E. Baeck
3.2. PROFILES, THIN WALLED APPROACH Page 89
dict
Python’s build-in dictionary class
ProfileDB
The class ProfileDB is based on a
a dictionary. Profile instances are
− self. init (..): constructor
are stored like in a database.
+ self.list(..): print instance’s data
22 # the View method calls the View method of it’s items with a False Flag.
23 # if there is no item, the case is handled with an exception block
24 def view(self):
25 iobj = 0 # initialize the object counter
26 for name in self: # iterate the keys of the dictionary
27 try: # open the try block
28 self[name].View(False) # try to write the png file
29 except: # if not possible log it to the log file
30 self.appendLog(" Error: No profile key %s found, slot %d" % \
31 (name,iobj))
32 iobj += 1 # increment the counter
To check the database class ProfileDB we write a little script, which first creates a ProfileDB instance.
Then we create a UProfile instance with the values of the U100. This instance is stored in the dictionary
using the key of it’s name U100. Then we create a second UProfile instance with the values of the U140
and store it as well in the dictionary using it’s name U140 as it’s key. After that we simple call the
ProfileDB instance method list. The data of the two profiles are listed on the screen and into the log file.
After the job is done, we print the png files of our profiles. The code of the testing environment is given
below, the resulting png files are shown in figure .
8.5.2018
Page 90 Analysis of Structures - SS 15
1 ’’’
2 This testing example implements a little profile
3 database. Two U-profiles are created and stored in
4 the database. Then the whole content of the database
5 is printed using the AppendLog method of the base class
6 ’’’
7 # package module class
8 from Profile.UProfile import UProfile
9 from Profile.ProfileDB import ProfileDB
10
11
E. Baeck
Part II
91
4
In this chapter we talk about the Abaqus Student Edition Licence 6.10.. A main aspect will be the
development of Python programs, which should automate the creation of FE models and the subsequent
calculation and preprocessing.
In this chapter we talk about the Abaqus Student Edition Licence 6.10. GUI1 .
Figure 4.1 shows the Abaqus GUI. A very important item is the combo box to select the module. The
selected module loads the specific menu items. The left window shows the Abaqus object tree. The
bottom window contents an output window for the output messages and the command window for the
Python commands.
1
Graphical User Interface is a window driven program which contents all commands in terms of menu items, buttons, boxes
and so on which are commonly called widgets.
93
Page 94 Analysis of Structures - SS 15
• The Python command window offers the possibility to execute single Python commands.
• The GUI offers the possibility to record interactive actions in a Python script format. So we can
record and replay everything we do within the GUI.
The Python interpreter creates the input for the CAE kernel. The CAE kernel creates the input stream for
the Abaqus FE-Module.2
2
The input file for the Abaqus FE-Module is a simple Text file, the classical input file, which can also be written ’by hand’.
E. Baeck
4.3. A MODELING CHAIN Page 95
Figure 4.2 shows how to create a Finite Element model in Abaqus/CAE. It Create Database
is not possible to create elements and nodes directly. Element and nodes are
only created by the mesh generator, which works an the geometric objects, Module Sketch
which are created drawing a sketch. Draw a sketch
The only FE model parameter, which are created directly, are the material Module Part
properties and the section values. This properties are created within the Create a part and
module Property. The properties are then assigned to the geometric objects assign the sketch
(lines, areas and volumes).
After having created a sketch the sketch has to be assigned to a part. If no Module Property
part exists, a part hast to be created. The properties (materials and section Create a properties, ma-
data) are assigned to the sketches’ geometric objects. terials and sections, as-
sign them to sketch lines
To create a mesh, an instance is needed, so an instance has to be created.
The part with the sketch are assigned to the instance for later meshing. Module Assembly
Loadcases are modeled in terms of load steps. So a new step has to be cre- Create an instance and
ated as a container for loads and boundary conditions. Loads and bound- assign the part to it
aries are assigned to the geometric objects of the sketch which were as-
signed to a part before. Module Step
Create a step as
To create the mesh, the mesh’s control parameters should be configured and
container for a load case
the element types are to be assigned. Then the instance can be meshed.
After the mesh is created, the complete model can be assigned to a job. To Module Load
calculate the results the job has to be submitted. Create loads and
boundary condi-
tion within the step
Module Mesh
Set Seeds, elements
per length select and
assign element type
mesh the instance
Module Job
Create a Job and submit
Module Postprocessing
Visualization
and Evaluation
Figure 4.2:
Modeling Chain Diagram
8.5.2018
Page 96 Analysis of Structures - SS 15
Lx
4.4.1 Create a Database Figure 4.3: 3 Trusses
Module: Sketch
Sketch => Create => Name: ’Truss-Example’ => Continue
Add=> Point
=> enter coordinates (0,0), (1000,0), (1000,1500), (0,1500)
Add => Line => Connected Line
=> select (0,0) node with mouse, then (1000,0) node,
right click => Cancel
Add => Line
=> Connected Line
=> select (0,0) node with mouse, then (1000,1500) node,
right click => Cancel
Add => Line
=> Connected Line
=> select (0,0) node with mouse, then (0,1500) node,
right click => Cancel
=> Done
Module: Part
Part => Create => Name: ’Part-1’,=> select 2D Planar, Deformable, Wire
=> Continue
Add => Sketch => select ’Truss-Example’ => Done => Done
E. Baeck
4.4. A LITTLE INTERACTIVE WARM UP EXAMPLE Page 97
Module: Property
Material => Create => Name: ’Steel’, Mechanical, Elasticity, Elastic
=> set Young’s modulus = 210000, Poisson’s ratio = 0.3 => OK
Section => Create => Name: ’Truss-Section’, Beam, Truss => Continue
=> set Material: ’Material-1’,
Cross-sectional area: 2
Assign Section => select all elements by dragging mouse => Done
=> ’Truss-Section’ => OK => Done
Module: Assembly
Instance => Create => ’Part-1’ => Independent (mesh on instance) => OK
Module: Step
Step => Create => Name: ’Step-1’, Initial, Static, General => Continue
=> accept default settings
=> OK
Module: Load
Load => Create => Name: ’Step-1’, Step: ’Step 1’, Mechanical,
Concentrated Force => Continue => select node at (0,0) => Done
=> set CF1: -10000 set CF2: -10000 => OK
Module: Mesh
Seed => Edge by Number => select entire truss by dragging mouse
=> Done => Number of elements along edges: 1 => press Enter => Done
Mesh => Element Type => select entire truss by dragging mouse => Done
=> Element Library: Standard,
Geometric Order: Linear: Family: Truss => OK => Done
8.5.2018
Page 98 Analysis of Structures - SS 15
Module: Job
Job => Create => Name: Job-1, Model: Model-1 => Continue
=> Job Type: Full analysis, Run Mode: Background,
Submit Time: Immediately => OK
E. Baeck
5
In this chapter we implement to example scripts, to discuss the automation in Abaqus using the Python
script language.
1. 3 Trusses
The first script gives the implementation of the interactive example, a little 3 trusses system with
one concentrated load. The calculation is performed automatically for a linear analysis.
2. U Profile
The second script gives the implementation of the automated model creation of U Profile using the
thin-walled approach (see also section 3.2 and B.1). The calculation is performed automatically
for a linear analysis and a buckling analysis.
Within this section the implementation of a script is shown, which automates the example of section
4.4. With the change of the parameter’s values, every system can be calculated with the execution of the
script.
Creating the calculation model we follow our outlines discussed in section 4.3. To avoid problems with
existing project files, we first delete an old database, if exist. Then we set the work directory by the use
of Python’s standard chdir function.1
To get the Python code for the necessary steps, we can simple run the macro recorder and record the
interactive actions. If you do this, then it’s recommended to save the macro file into the work directory
and not into the home directory. The recorded macros are saved into the file abaqusMacros.py.
Note, that the work directory will be set, if the script is executed.
Within the script code the following steps are numbered in the same way.
99
Page 100 Analysis of Structures - SS 15
After having selected the lines the truss section will be assigned by the part’s method
SectionAssignment. We have to specify the region and the name of the section.
E. Baeck
5.1. 3 TRUSSES SCRIPT Page 101
– synchronous analysis
In this case the script halts for completion of the calculation. This can be obtained by the
usage of the job classes’ method waitForCompletion. The next commands of the script
are executed after the calculation is completed.
– asynchronous analysis
In this case the script does not halt for completion and the next instructions are executed
immediately. To automate the analysis of the results we have to set up a call back function.
This function is executed automatically after the calculation is done.
8.5.2018
Page 102 Analysis of Structures - SS 15
1 # copy the next line into the abaqus command window and execute
2 # execfile("c:\\CM\\Cm-AoS\\WS1011\Abaqus\\3Trusses.py")
3
8 modelname = ’3Trusses’
9
17
18 import os # os tools
19 os.chdir(r’c:\\cm\\Cm-AoS\\WS1011\\Abaqus’)
20
21
22 # set up parameters
23 dx = 1000. # length in x
24 dy = 1500. # length in z
25 A = 13.5*100. # U100 area
26 Fx = -100000. # horzontal load
27 Fy = -100000. # vertikal load
28 EMod = 210000. # Young’s module
29 nue = 0.3 # Poisson’s ratio
30
E. Baeck
5.1. 3 TRUSSES SCRIPT Page 103
37
8.5.2018
Page 104 Analysis of Structures - SS 15
122 # - note: wait for completion, if the result values should be read form DB
123 myJob.waitForCompletion()
124
125
E. Baeck
5.1. 3 TRUSSES SCRIPT Page 105
Figure 5.2 shows the system with it’s loads and boundary condition (see figure 4.3 too). All points are
fixed but not lower left. Here we see the applied point loads in down and left direction.
Figure 5.2 shows the magnitude of displacement on the deformed truss structure.
8.5.2018
Page 106 Analysis of Structures - SS 15
The goal of our next example is, to create a mesh from a 2 dimensional sketch of
an U geometry by extrusion. Figure 5.2 shows an U profile with it’s parameters
[6]. The U profile geometry is used to create a FE model of a single span girder,
shown in figure 5.4. The girder has a length of L and will be loaded with a line
load q. The boundary conditions should be set according to the simple single
girder system.
The model of the U profile is created step by step according to the modeling chain
diagram (figure 4.2). The created mesh is shown in figure 5.9. Figure ?? shows
the load onto the upper flange of the girder. The girder is supported on both ends
at the lower flange’s edges.
Additional point support is needed to avoid longitudinal and transversal move- Figure 5.3: U Profile
ments as well as rigid body rotations. If we would not do this, it would be like
walking on perfect ice. We may glide in both horizontal directions and may rotate around the vertical
axis without any resistivity. So the stiffness matrix of the girder would be singular without the suppres-
sion of this degrees of freedom (dof ). So we have to fix three dof s which will suppress this rigid body
moves on an arbitrary point in the system. After the calculation is done we will see, whether the choice
was ok, if the reaction forces on this fixed dof s are numerically vanishing.
Figure 5.4 shows the single span girder in terms of a simple beam. The q
load q is distributed constantly on the girder length L. One end of the
girder is supported hinged and the other side is supported with a roller
support. L
• According to the calculation switches the script automatically should be able to do a linear static
calculation, a buckling analysis or a frequency analysis;
• for a calculation with loads, the script should check automatically the load balancing, i.e. it should
check whether the applied load will be totally seen as reaction forces;
• the script should find all nodes along a given longitudinal system fiber;
E. Baeck
5.2. U-GIRDER SCRIPT Page 107
As opposite to our first example, the three trusses (section 5.1), in this case we want to apply the strategy
of OOP to our script and want to implement it in terms of classes.
• UGirder should have printing features, deriving them from our class Base like in the Python part
(see section 3.2.9).
Thus we get the following class structure (see 5.5). Following the concept, we have discussed in part 1
section 3.2, all classes are derived from the superclass Base, which should provide all common features.
InputData
Base UGirder
ResultData
The class UGirder should get methods for every build step of the system. After the calculation is done
we need some additional methods, which are discussed later.
• createStep, creates the load step according to the desired analysis mode.
• createBCs, creates the boundary conditions inside the last created load step.
• createLoads, creates the loads inside the last created load step.
8.5.2018
Page 108 Analysis of Structures - SS 15
Figure 5.6 shows the UML class diagram of the InputData class. This class is used to assemble, check
and work up the girder’s parameters.
InputData
Besides the parameters discussed in the table above, there are some other attributes in the class, which
are used to prepare or initialize the parameter set for the calculation. This attributes are explained inside
the code.
E. Baeck
5.2. U-GIRDER SCRIPT Page 109
The following listing 5.2 shows the implementation of the class InputData.
4 # module content/class
5 from Base import Base
6
7 # input dataset
8 class InputData(Base):
9
10 # contructor method
11 def __init__(self):
12
13 # initialize Base-Data
14 Base.__init__(self)
15
21 ## dimensions: N, mm, s
22
30 # system parameter
31 self.len = 4.0 # length [m]
32
33 # material parameters
34 self.ymod = 210000. # N/ m m Young’s module
35 self.nue = 0.3 # Poisson ratio
36 self.rho = 7.8e-6 # mass density kg/ m m
37
38 # loads
39 self.load = 10. # load in kN
40
8.5.2018
Page 110 Analysis of Structures - SS 15
53 self.numBIterX = 100
54 self.numBVectors = self.numBEigen + 10
55
62 ## project parameters
63 self.prjName = "U-Girder"
64 self.jobName = self.prjName;
65
66 # output control
67 self.bPngFiles = True # flag to control the file export
68
E. Baeck
5.2. U-GIRDER SCRIPT Page 111
Figure 5.7 shows the UML class diagram of the ResultData class. This class is used to hold the calculated
result data.
ResultData
To get the maximal vertical displacement of a very stiff girder fiber to fade out the cross displacement, we
have to select the fiber’s nodes. This node data is stored in the dictionarry nodePos. After the calculation
is done, we can search for the maximal vertical displacement in the subspace of the fiber nodes.
The following listing 5.3 shows the implementation of the class ResultData.
4 ’’’
5 container for result data
6 ’’’
7 from math import fabs
8 from Base import Base
9
10 class ResultData(Base):
11
12 # constructor
13 def __init__(self):
14 self.nodePos = {} # to store the node coordinates and it’s label
15 self.nodeRFo = {} # to store the reaction forces
16 self.nodeDis = {} # to store the node displacements
17 self.sumRFo = [0.,0.,0.] # sum vector of the reaction forces
18
8.5.2018
Page 112 Analysis of Structures - SS 15
From figure 5.5 we can see, that like in the case of the TWA (see section 3.2 too) all classes in our script
are derived from a superclass, which is called Base.
The only change we make is, to replace the log files name with UGirder.log. The classes’ implementation
is given in listing 5.4.
4 ’’’
5 all common functions and variables
6 ’’’
7 # module item our name of this item
8 from datetime import datetime as time
9 import os
10
11 class Base():
12
16 # constructor
17 def __init__(self,log = ""):
18 if log != "": Base.__log = log
19 Base.__count += 1
20 self.appendLog("instance %d created" % Base.__count)
21
22 # destructor
23 def __del__(self):
24 Base.__count -= 1
25
42 print textout
E. Baeck
5.2. U-GIRDER SCRIPT Page 113
The UGirder class will be implemented to organize, calculate and analyze the data. The class’ UML
diagram is shown in figure 5.8.
UGirder
The class’ constructor creates an InputData and a ResultData object. To be sure, that all modules are
compiled before execution, i.e. a kind of rebuild, we have to reload this modules. This is only working,
if we load them as entire module (see section A.1 too).
Further methods are implemented to add feature by feature to our U-Girder system. All this steps are
done within the method createSystem.
The fist part of the class’ listing 5.5 shows all methods, to create the geometric system and its mesh. The
mesh we can see in figure 5.9.
Listing 5.5: Implementation of U-Girders’ Main Class UGirder Class, Part System
4 ’’’
5 the girder’s main class
6 ’’’
7 # for testing only, to be sure, that every modul will be compiled
8 import Base
9 reload(Base)
10 import InputData
11 reload(InputData)
12 import ResultData
13 reload(ResultData)
14
15 # UGirder imports
16 from Base import Base
8.5.2018
Page 114 Analysis of Structures - SS 15
29 # constructor
30 def __init__(self):
31 Base.__init__(self)
32 Base.resetAll()
33
72 # do a little abbreviation
E. Baeck
5.2. U-GIRDER SCRIPT Page 115
73 data = self.input
74
127 # - Web
128 self.selectWeb = self.part.faces.findAt( ( ( 0., 0., data.len/2.) ,),)
8.5.2018
Page 116 Analysis of Structures - SS 15
129 self.part.SectionAssignment(region=(self.selectWeb,),sectionName="Web")
130
148 # o web
149 select = self.part.edges.findAt( ( (0.,0., 0.), ),
150 ( (0.,0., data.len), ),)
151 self.part.seedEdgeByNumber(edges=select,number=data.webSeed)
152
163 # searching for fiber nodes, i.e nodes on the center line
164 def getFiberNodes(self):
165 self.appendLog("find nodes on center fiber...")
166
E. Baeck
5.2. U-GIRDER SCRIPT Page 117
185
To be able to do an independent calculation for the linear static, the stability and the frequency analysis,
we first delete an existing load step called Step-1 and then we create the desired type of load step. If we
do this, we easily can run the calculation of all load steps within one calculation loop.
Listing 5.6: Implementation of U-Girders’ Main Class UGirder Class, Part Loads
2 # create step
3 def createStep(self,type):
4 self.appendLog("create step of type ’%s’..." % self.input.stepNames[type])
5 self.input.stepType = type
6 # first we have to delete an old created step, to clear the momory
7 if len(self.model.steps) > 1: del self.model.steps["Step-1"]
8 # then we create the new one
9 # create a linear static step with it’s data
10 if type == self.input.LINEAR:
11 self.model.StaticStep(name="Step-1",previous="Initial")
12 self.createBCs(type)
13 self.createLoads(type)
14
8.5.2018
Page 118 Analysis of Structures - SS 15
24
Figure 5.10 shows the girder with it’s loads and the boundary conditions after the creation of the steps
Linear Static and Buckling.
Listing 5.7: Implementation of U-Girders’ Main Class UGirder Class, Part Job
E. Baeck
5.2. U-GIRDER SCRIPT Page 119
31 if self.input.stepType == self.input.LINEAR:
32 self.analyzeLinearStep()
33 elif self.input.stepType == self.input.BUCKLING:
34 self.analyzeBuckling()
35 elif self.input.stepType == self.input.FREQUENCY:
36 self.analyzeFrequency()
37
8.5.2018
Page 120 Analysis of Structures - SS 15
47 # - select results
48 # |the last frame
49 frame = self.odb.steps["Step-1"].frames[-1]
50
66 # iterate and print the RF container (dictionary: -> the key is given)
67 self.appendLog("--no ---------RFx ---------RFy ---------RFz")
68 for label in result.nodeRFo:
69 nodeRF = result.nodeRFo[label]
70 self.appendLog("%4d %12.3e %12.3e %12.3e" % \
71 (label,nodeRF[0],nodeRF[1],nodeRF[2]))
72
84 varList = ("U1","U2","U3")
85 for var in varList:
86 # plot into the viewport
87 self.viewport.odbDisplay.setPrimaryVariable(
88 variableLabel=’U’,
89 outputPosition=NODAL,
90 refinement=(COMPONENT,var))
91
E. Baeck
5.2. U-GIRDER SCRIPT Page 121
115 self.viewport.odbDisplay.display.setValues(plotState=(CONTOURS_ON_DEF,))
116 self.viewport.odbDisplay.setFrame(step="Step-1", frame=i+1)
117 self.viewport.view.fitView()
118
137 self.viewport.odbDisplay.display.setValues(plotState=(CONTOURS_ON_DEF,))
138 self.viewport.odbDisplay.setFrame(step="Step-1", frame=i+1)
139 self.viewport.view.fitView()
140
8.5.2018
Page 122 Analysis of Structures - SS 15
If we organize the girder code using classes the main program to run it will be very lightweight (see
listing 5.8). After setting up the work directory, where we will find the created files, we create the mesh
of the system. After this we run a loop over all implemented load steps and run the linear static, the
buckling analysis and the frequency analysis.
After the calculation is done the figures are drawn automatically and stored into png files.
Listing 5.8: Implementation a Main Code for U-Girders to Automate the Calculation
1 __author__ = ’baeck’
2
3 ’’’
4 we can start the script using the followning command:
5 execfile(r’[path]\mainUGirder.py’)
6 execfile(r’c:\unidue\CM\Cm-AoS\AOS-BookOfExamples\Py\Code\Abaqus\UGirder\mainUGirder.py’)
7 ’’’
8
E. Baeck
5.2. U-GIRDER SCRIPT Page 123
Figure 5.11 shows the resulting displacements in 1(x), 2(y) and 3(z) direction of a linear analysis.
8.5.2018
Page 124 Analysis of Structures - SS 15
E. Baeck
5.2. U-GIRDER SCRIPT Page 125
8.5.2018
Page 126 Analysis of Structures - SS 15
E. Baeck
5.2. U-GIRDER SCRIPT Page 127
8.5.2018
Page 128 Analysis of Structures - SS 15
E. Baeck
Part III
Appendix
129
Appendix A
If a module is loaded into the Python interpreter to run a script, all changes within the loaded modules
became active, if the script is reloaded. To reload a module on the fly, we have to apply the function
reload(). If a module should be reloaded, we have to import it first without the from key. After the
module is loaded, the module name is declared and we can start the reload() command. After the
reload() we can import the module with the from key.
1 # forced reload for the developer step
2 import InputData # this binds the module to the symbol
3 reload(InputData) # now we reload in any case
4
131
Page 132 Analysis of Structures - SS 15
E. Baeck
Appendix B
Some Theory
Within this chapter the formulas for the section properties of a thin walled model are given.
A thin walled model for a profile section consists of a set of lines which describes the profile section
geometry at the centerline.
The Area is approximately the sum of the areas of the lines of the thin walled model.
Z n
X
A= eµ · dA ≈ eµ,i · Li · ti (B.1)
A i=1
The first moments of an area are the area integrals given below. The (y,z) values are related to an given
coordinate system.
Z n
X
Sy = eµ · z · dA ≈ eµ,i · z i · Ai
A i=1
Z Xn
Sz = eµ · y · dA ≈ eµ,i · y i · Ai (B.2)
A i=1
133
Page 134 Analysis of Structures - SS 15
The moments of inertia can be calculated with the formulas below. If we have a given arbitrary coordinate
system in general we have three values of inertia the Iy , the Iz and the mixed Iyz . If we use the main
coordinate system, the mixed moment of inertia is vanishing, so we use the symbols Iξ and Iη .
Z n
X
2
(zb,i − za,i )2 /12) + z 2i · Ai
Iy = eµ · z · dA ≈ eµ,i ·
A i=1
Z n
X
eµ · y 2 · dA ≈ (yb,i − ya,i )2 /12) + y 2i · Ai
Iz = eµ,i ·
A i=1
Z Xn
Iyz = eµ · y · z · dA ≈ eµ,i · (((yb,i − ya,i )(zb,i − za,i )/12) + y i · z i ) · Ai ) (B.3)
A i=1
To solve an integral like Iy = A z 2 · dA for a polyline we can split up the integral into the sum of
R
To solve an integral for a polyline segment we simple calculate it for the center of mass, because a simple
shift only will give us an additional term, the Steiner term. If we now want to calculate the polyline
integral at the center of mass we rotate the coordinate system by an angle ϕ into the line’s longitudinal
direction, because the transversal dimension, the thickness, is constant and so the respective integral will
be trivial.
E. Baeck
B.1. SECTION PROPERTIES Page 135
The coordinates of the center of mass are calculated with the arithmetic mean. Because the numerator of
the arithmetic mean is identical with the first moment of the area (see section B.1.2) and the denominator
is identical with the area of the profile, which is calculated in section B.1.1 we can use this values.
R
y · dA Sz
yc = AR =
dA A
R A
z · dA Sy
zc = AR = (B.8)
A dA A
If we know the center of mass coordinates given in section B.1.4 we can calculate the moments of inertia
with respect to the center of mass using Steiner’s Theorem as follows.
Iy,c = Iy − zc2 · A
Iz,c = Iz − yc2 · A
Iyz,c = Iyz − yc · zc · A (B.9)
8.5.2018
Page 136 Analysis of Structures - SS 15
To get the moments of inertia Iη and Iξ we have to transform the moments of inertia into the main
coordinate system. Using this coordinate system the mixed moment of inertia is vanishing.
1
The rotation angle ϕ should be shifted into the intervall [−π/2... + π/2]. To avoid a zero division calculating the rotation
angle ϕ a special version of the atan function should be used, which is able to handle the pole problem. In Python like in C this
function is called atan2(x, y), which calculates the atan( xy ).
E. Baeck
Appendix C
There are lot of IDEs available for the development of Python software. Most of them are commercial.
One very nice IDE especially for large development projects with a lot of Python files is called Aptana.
Apatana is a special version of the free Eclipse IDE. For this IDE there is a plugin available, which is
called PyDev. To use this IDE first you have to install the basis version of Aptana and then you should
install the plugin and select the desired Python version, which should be installed before. An example
project within the Aptana is shown in figure C.1.
137
Page 138 Analysis of Structures - SS 15
PyCharm is an IDE (integrated development environment) which was developed from JetBrains1 . You
can download a free community edition, which we will use in our lecture. The IDE is available for
Windows, Linux and in MacOS.
In contrast to the little PyWin-IDE. PyCharm is working like modern IDEs with projects, i.e. everything
you want to develop, is put into a container, which is called a project. This avoids the sometimes up
coming confusion, if you are working only with single files.
C.2.2 A Hello-Example
If we want to implement the famous Hello World example, known as a general start up, we have to do
this in two steps.
2. We have to create a new Python file, which should print the desired output to the screen.
First of all we have to start the IDE clicking on the icon on the desktop or running the exe-file from the
installation folder. The start up page is display like shown in figure C.2.
After having clicked on ”Create New Prjoject” the dialogs come up, which specifies the project, see
figure C.3. We have set up a new project name. The name is used to specify the project folder. You can
1
You can download the software using the following link https://www.jetbrains.com/pycharm/download/
E. Baeck
C.2. THE PYCHARM - IDE Page 139
edit the default project folder name. In the third control you have to select the desired Python interpreter.
In our case the version 2.7.3 was selected.
After having created the empty Hello project we see the following page, see figure C.4.
Now we have to create a new Python file, which should print the famous message to the screen. So we
select the menu item File/New... and from the displayed list we select the item file. Then a dialog is
displayed to enter the file’s name. Here we don’t need to input the absolute file name with it’s folder
name. This we see in figure C.5.
After having created a new empty file with the name hello.py, we input the one and only statement of our
new application, the statement print "Hello World!". This we see in figure C.6.
To run the application, we have to select the project Hello and click the green run button. If this is done,
a new window if not already opened will be displayed with the console output, i.e. with the message
”Hello World!”. This we can see in figure C.7.
8.5.2018
Page 140 Analysis of Structures - SS 15
E. Baeck
Appendix D
Conventions
The following code convention [7] is published by Oracle (successor of Sun Microsystems, Inc). We
apply this convention to choose names for our software items.
1. Classes
Class names should be nouns, in mixed case with the first letter of each internal word capitalized.
Try to keep your class names simple and descriptive. Use whole words-avoid acronyms and ab-
breviations (unless the abbreviation is much more widely used than the long form, such as URL or
HTML).
2. Methods
Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each
internal word capitalized.
3. Variables
Except for variables, all instance, class, and class constants are in mixed case with a lowercase first
letter. Internal words start with capital letters. Variable names should not start with underscore _
or dollar sign $ characters, even though both are allowed.
Variable names should be short yet meaningful. The choice of a variable name should be
mnemonic- that is, designed to indicate to the casual observer the intent of its use. One-character
variable names should be avoided except for temporary ”throwaway” variables. Common names
for temporary variables are i, j, k, m, and n for integers; c, d, and e for characters.
4. Constants
The names of variables declared class constants and of ANSI constants should be all uppercase
with words separated by underscores ("_"). (ANSI constants should be avoided, for ease of
debugging.)
141
Page 142 Analysis of Structures - SS 15
E. Baeck
Appendix E
Parallel Computing
E.1 Threads
The most general parallelisation of code is given in the usage of so called threads. A thread is like an
application, which is started and which is running then independent of it’s creating program. Threads
are often used, to run some time consuming events in the background of an interactive program. If
this activity would not run independent in the background, it would block all interactive events of the
application, like clicking on buttons or scrolling the window contents and the user would have the feeling,
that this application is hanging.
Threads run parallel on one processor using a task switch strategy. For example, if we run a browser
and a mailing application on an old computer, we get the feeling, that they are be executed in parallel.
With on processor we can not do this. Applications are executed piecewise sequentially. If the hardware
however comes with more than one processor, in general the operating system, i.e. Windows in our case,
is able to distribute this threads onto all available processor, so that they can be executed in parallel. This
we can see, checking the processor loads.
The disadvantage of this kind of threads is, that in general the end of a thread have to be caught by
the caller, so that the caller is able to use the outcome of the thread. This in general costs an effort of
administration.
In contrast to general threads we can use a so called Multi-Processing-Pool. This pool is filled this
threads of the same kind. If the calculation is started, all this threads are executed on a given set of
processors. This execution is sequential from the view of the calling program, i.e. the calling program is
calling the Multi-Processing-Pool being executed and will halt until all threads are executed, so that we
will not need a code which is synchronizing the execution of the threads.
A typical use case for this is a simple loop with independent cycles.
A really nice example, which shows the usage of a Multi-Processing-Pool is the calculation of the so
called Mandelbrot set1 . This calculation can be split up in several independent cycles. To show the
1
Benoı̂t B. Mandelbrot, described the Mandelbrot set as a number of complex numbers.
143
Page 144 Analysis of Structures - SS 15
performance of parallel execution we introduce the TimeCheck class given in the listing .
with z, c ∈ C
If the absolute value is less equal two it’s a Mandelbaum set point. Otherwise it’s not. In figure E.1 the
Points of the Mandelbraum set are plotted in the complex number plane.
The function mandelbrotCalcRow calculates the the data for one row of the Mandelbrot set picture.
We put this function partialCalcRow with its function parameters xrange(h) into a map, which
calculates the values for all function parameters. The function partial is used to reduce the number of
arguments of the function mandelbrotCalcRow simply to one, i.e. the last non set, i.e. the ypos
argument. So the parameter space is reduced from 4 to 1. For this dimension, i.e. ypos, the map is
created. On a i7 processor we need 21 seconds to get the result.
E. Baeck
E.2. A MULTI-PROCESSING POOL Page 145
37 plt.imshow(mandelImg)
38 plt.savefig(’mandelimg.png’)
39 # plt.show()
If we now want to use the power of our i7 processor, i.e. if we want to use the 4 available cores, we have
to distribute the calculation load of the Mandelbrot set rows onto this cores. This we see in listing E.3.
30 # the pool.map only accepts one iterable, so use the partial function
31 # so that we only need to deal with one paramter.
32 # the pool method map runs the set in parallel
33 mandelImg = pool.map(partialCalcRow, xrange(h))
34 pool.close() # we are not adding any more processes and close
35 pool.join() # tell it to wait until all threads are done before going on
36
8.5.2018
Page 146 Analysis of Structures - SS 15
37 return mandelImg
38
Figure E.1 shows the result of our calculation. Every cycle is calculating one row of this picture.
E. Baeck
Appendix F
Sometimes the standard parameters of the Abaqus GUI are really unlucky. So the standard font is set
to 8 points, i.e. it’s impossible to read the text inside the legend, if we create a standard figure with the
following code. The script will plot the calculated displacements colored onto the displaced system. In
a loop we select the displacement related to all coordinate axis.
1 # - create png-files of the displacement components u1, u2, u3 (x,y,z)
2 varlist = ("U1","U2","U3")
3 for var in varlist:
4
If we record the selection of a proper font we can use this code to set the font size automatically. The
following code snippet will do this (see figure F.2).
1 session.viewports[’Viewport: 1’].viewportAnnotationOptions.setValues(
2 triadFont=’-*-verdana-medium-r-normal-*-*-100-*-*-p-*-*-*’,
3 legendFont=’-*-verdana-medium-r-normal-*-*-100-*-*-p-*-*-*’,
4 titleFont=’-*-verdana-medium-r-normal-*-*-100-*-*-p-*-*-*’,
5 stateFont=’-*-verdana-medium-r-normal-*-*-100-*-*-p-*-*-*’)
147
Page 148 Analysis of Structures - SS 15
E. Baeck
F.2. SPECIFY VIEW Page 149
A view can be specified by setting the view direction, called Viewpoint and the Up vector. The Viewpoint
specifies the view direction. We should input a vector of this direction. Only the vector direction is
important not the vector length. The second vector specifies the up direction, so we have to specify this
direction with a vector again, whose direction only is important.
We can input this data within the following dialog of the View menu (see F.3)..
In following code we can see, that we select from the session’s viewport container the standard view-
port "Viewport: 1". It’s view member provides a method to specify the directions discussed above.
1 session.viewports[’Viewport: 1’].view.setViewpoint(viewVector=(1, -1, 1),
2 cameraUpVector=(0, -1, 0))
8.5.2018
Page 150 Analysis of Structures - SS 15
E. Baeck
Bibliography
[5] D. G. Taggart
University of Rhode Island, 2009
[6] O. Lueger
Lexikon der Technik, 1904
151
Index
:, 31 area, 133
arithmetic mean, 135
Abaqus as, 17
abaqusMacros, 99
BaseWire, 100 Basic, 24
close, 102 bit’s values, 19
ConstrainedSketch, 100 break, 28
DisplacementBC, 101 bytecode, 5
element type C, 5, 19, 23, 24, 27
T2D2, 101 C#, 5
elemType, 101 Camel Case, 15
fieldOutputs, 102 center of mass, 135
frame, 102 Charles Simonyi, 15
generateMesh, 101 chdir, 99
getSequenceFromMask, 100 class
instance, 100 AList, 75, 79
job, 101 Base, 67
material, 100 Element, 71
mesh, 101 Node, 69
model, 99 Profile, 75
openOdb, 102 ProfileDB, 88, 89
part, 100 UProfile, 75, 84
regionToolset, 101 classes, 55
rootAssembly, 100 code blocks, 25
SectionAssignment, 100 complement, 18
seedEdgeByNumber, 101 ComTypes, 7
session, 101 conditional assignment, 32
setElementType, 101 constructor, 55
StaticStep, 101 continue, 28
step, 102 cos, 17
submit, 101 count, 41
TrussSection, 100
datetime, 47
values, 102
day, 48
vertices, 101
def, 31
viewport, 101
derivative, 36
visualization, 102
destructor, 56
waitForCompletion, 101
dictionary, 42, 88
append, 41
Aptana, 137 e/E format, 23
152
INDEX Page 153
8.5.2018
Page 154 Analysis of Structures - SS 15
sin, 17
site-packages, 6
sort, 41
stack, 41
strings, 39
Sun Microsystems, Inc., 15
The Beatles, 42
timedelta, 47
Tkinter, 75
try, 81
tuple, 31, 39
type, 24
type checking, 35
UML, 53
aggregation, 54
class diagram, 53
composition, 54
inheritance diagram, 54
note diagram, 53
note diagram assignment, 53
version, 6
viewport annotations, 148
while, 27
Windows, 138
year, 48
E. Baeck