Web5129 PDF

Download as pdf or txt
Download as pdf or txt
You are on page 1of 93

METHODS FOR INTEGRATING FORTRAN BASED FINITE ELEMENT APPLICATIONS IN A SCRIPTING ENVIRONMENT

MARTIN ROOS

Structural Mechanics

Masters Dissertation

Detta r en tom sida!

Structural Mechanics
ISRN LUTVDG/TVSM--05/5129--SE (1-XXX) ISSN 0281-6679

METHODS FOR INTEGRATING FORTRAN BASED FINITE ELEMENT APPLICATIONS IN A SCRIPTING ENVIRONMENT
Masters Dissertation by MARTIN ROOS

Supervisors: Jonas Lindemann and Ola Dahlblom, Div. of Structural Mechanics

Copyright 2005 by Structural Mechanics, LTH, Sweden. Printed by KFS I Lund AB, Lund, Sweden, Month, 2005. For information, address: Division of Structural Mechanics, LTH, Lund University, Box 118, SE-221 00 Lund, Sweden. Homepage: http://www.byggmek.lth.se

Detta r en tom sida!

Preface
The work presented in this Masters thesis was carried out at the Division of Structural Mechanics at Lunds University, Sweden, during September 2004 - February 2005. I would like to express my gratitude to my supervisors, Professor Ola Dalhblom and PhD Jonas Lindemann. Ola Dalhblom for helping me to nd this Masters thesis and start it up. Jonas Lindemann for supporting me during the entire process and for the discussions we had regarding the topics in this work. I am also very grateful to have had the possibility to use the resources at the Division of Structural Mechanics and thanks to Mr Bo Zadig for helping me with the graphics and printing. Finally I would like to thank all other students in the Masters thesis room for giving me motivation and laughter.

Lund February 2005, Martin Roos

Abstract
The course Software Development for Technical Systems at the division of Structural Mechanics teaches students techniques for implementing nite element applications with both user interface and computational code. Currently Borland Delphi environment is used for the user interface and Fortran is used for the computational part. This masters thesis is an eort to study methods of integrating Fortran with script languages and user interface to create more exible and easier to use software. An interesting candidate for user interface and computational environment is Python. Python is a script language, which is easy to use and learn for non-programmers and yet powerful enough to use as a scripting environment for computational codes. A nite element application is developed where the computational code is written in Fortran and the user interface in Python. The main task to solve is how to link Fortran and Python. To perform the link a tool, Fortran to Python interface generator (F2PY) is used after an evaluation of dierent tools. The test application shows that F2PY creates an interface in a single step, no advantages of Fortran are lost, all major Fortran functions are supported and a F2PY created module is as easy to use as a built-in function in Python. The disadvantage of F2PY is that it need ve prerequisites. Overall F2PY fullls all requirements on a link between Fortran and Python. Python has all features a scripting languages shall have, easy code structure, rapid development and the ability to glue components together. Python also gives the user possibility to create a graphical user interface (GUI) with or without a GUI-builder. Finally all parts that are used are platform independent. This result in that it is recommended to replace Borland Delphi with Python in the course Software Development for Technical Systems.

iii

Sammanfattning
Kursen Programutveckling f or Tekniska System p a avdelningen f or Byggnadsmekanik l ar ut tekniker f or att implementera nita element program som bets ar av en ber akningsdel och ett anv andargr anssnitt. F or tillf allet anv ands utvecklingsmilj on Borland Delphi f or anv andargr anssnittet och Fortran f or ber akningskoden. Detta examensarbete syfte ar att studera metoder f or att integrera Fortran med skriptspr ak och anv andargr anssnitt f or att utveckla mer exibla och l attanv anda applikationer. Ett intressant programmeringsspr ak f or anv andargr anssnittet och som ber aknings skal ar Python. Python ar ett skriptspr ak som ar anv andarv anligt och l att att l ara f or nyb orjare men and a tillr ackligt kraftfullt f or att anv andas som en skript milj o f or ber akningskod. Ett nita element program a ar ber akningskod a r utvecklat d r skriven i programmeringsspr aket Fortran som integreras i scriptspr aket Python, huvuduppgiften ar att skapa en fungerande l ank mellan Fortran och Python. Gr anssnittet till l anken skapas med ett verktyg, Fortran to Python interface generator (F2PY) som valdes efter en genomg ang av olika verktyg. Under utvecklingen av nita element programmet ses att F2PY skapar ett gr anssnitt i ett steg, integreringen av spr aken g ors utan att Fortrans ber akningsegenskaper f ors amras, alla Fortran funktioner st ods av F2PY och en modul som ar skapad av F2PY ar lika enkel att anv anda som en inbyggd funktion i Python. Nackdelen med F2PY ar att det kr avs fem andra program installerade. Som helhet fungerar F2PY bra f or att skapa en l ank mellan Python och Fortran. Python uppfyller ocks a alla krav som st alls p a ett scriptspr ak, enkel struktur, snabb utveckling av applikationer och m ojligheten att skapa graska anv andargr anssnitt med eller utan en grask gr anssnitts byggare. Fortran och Python ar plattformsoberoende vilket F2PY ocks a ar. Detta resulterar i att det rekommenderas att byta ut Borland Delphi mot Python i kursen Programutveckling f or Tekniska System.

Contents
Preface Abstract Sammanfattning 1 Introduction 1.1 Background 1.2 Objective . 1.3 Limitations 1.4 Outline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i iii v 1 1 1 2 2 3 4 4 5 8 9 10 12 13 13 13 14 17 21 21 23 24 30 35 36

2 Mixed Language Programming 2.1 Static linking . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Dynamic linking . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Tools for generating interfaces to script languages . . . . . . 3 Scripting languages and computational code 3.1 Python . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 User Interfaces for Python . . . . . . . . . 3.1.2 Computational environment . . . . . . . . 3.2 Fortran . . . . . . . . . . . . . . . . . . . . . . . 3.3 Tools used in this work . . . . . . . . . . . . . . . 3.4 Fortran to Python Interface Generator (F2PY) . 3.4.1 Creating a Python module . . . . . . . . 3.4.2 Using F2PY generated modules in Python 4 Application cases 4.1 2D Truss . . . . . . . . . . . . . . . . . . . . 4.1.1 Quick review of former course layout 4.1.2 Interfacing Python with Fortran . . 4.1.3 User interface implementation . . . . 4.1.4 Final outline for 2D Truss . . . . . . 4.1.5 Python help and hints . . . . . . . . vii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.2

4.1.6 Python to executable le . . . . . . . . . . . . . . . . Graphical user interface for F2PY . . . . . . . . . . . . . . .

40 40

5 Summary and Conclusions 43 5.1 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 5.2 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 5.3 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Bibliography Appendices A Python Modules A.1 Start . . . . . . . . A.2 Mainframe . . . . . A.3 Base . . . . . . . . . A.4 Modeldraw . . . . . A.5 Elementproperties . A.6 Elementproperties ui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-1 A-1 A-1 A-8 A-14 A-21 A-24 45

B Fortran Modules B-1 B.1 Calcprog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B-1

viii

Chapter 1

Introduction
1.1 Background

The course Software Development for Technical Systems at the division of Structural Mechanics [21] teaches students techniques for implementing nite element applications with both user interface and computational code. Currently Borland Delphi environment is used for the user interface and Fortran is used for the computational part. This masters thesis is an effort to study methods of integrating Fortran with script languages and user interface to create more exible and easier to use software. The user interface has become more important and a natural part of computational programs because users often demand better graphical tools for creating complex models and viewing results. An additional advantage with better graphical interfaces is that the application reaches a larger user base. An interesting candidate for user interface and computational environment is Python. Python is a script language, which is easy to use and learn for nonprogrammers and yet powerful enough to use as a scripting environment for computational codes. Another advantage is the cost, Delphi is an expensive commercial application, Python is free and open source. Most students in this course are not experienced programmers, so the language must be easy to learn and understand, so that they can concentrate on the task instead of learning the intricate details of a complicated language.

1.2

Objective

This master thesis will investigate how forthcoming courses can be implemented with focus on Fortran integration in a script environment such as Python. The thesis will also investigate how the Python script-language can be used to develop user interfaces, in the same way as the Borland Delphi development environment has been used in former courses. A test application similar to the assignment in the existing course Software Development 1

for Technical Systems will be developed. The objective with the application is to evaluate if it is possible to use it in the new version of the course, it will also be considered if the application is user-friendly enough and platform independent.

1.3

Limitations

In this work the application case is developed in Windows and the graphical parts are tested both in Windows and Linux, but as no usable free Fortran 95 compiler is available for Linux at the time the F2PY created Python module is implemented on Windows. The test application does not have full support for all functions for a bar element. Fortran is not examined at the same levels as Python and F2PY since only minor changes are made in Fortran from the existing course.

1.4

Outline

Chapter 2: Mixed Language Programming Introduction how to mix dierent programming languages, both in Linux and Windows. Dierent tools that creates interfaces are introduced. Chapter 3: Scripting languages and computational code Distinguishing features for scripting languages are described. The programming languages and interface tools that will be used are described with focus on interface creation and graphical user interfaces. Chapter 4: Application Cases In this chapter two application cases are studied. The rst is an application similar to the assignment in Software Development for Technical Systems, which investigates how to implement a nite element application. The second application test if it is possible to use Python as a rapid application develop environment as well as a tool for integrating dierent computational software components.

Chapter 2

Mixed Language Programming


Integrating computational code with user interface code often has special requirements. These two parts often have dierent demands on the programming language. The graphical part must support rapid development and integrate well with other languages. The language implementing the computational part must be fast in execution and able to handle large amounts of data e.g. matrices. To combine these aspects it is often needed to mix languages to take the advantage of the features dierent languages can oer. According to Arnholm [8] a number of diculties has to be considered before using a mixed language support. Hence it is important not to add new diculties that are larger than the advantages. The main things to consider are that no new constraints should be added and that the complexity should not increase compared to using one language. If new constraints are added the lifetime of a project reduces and more complexity makes development inecient and increases maintenance costs. The described diculties above can be translated to the following requirements [8]: Source code must be possible to use on any platform. The procedure to make a link between languages must be easy to perform. Mixed languages shall not loose execution speed although a linking is made. All major features must be supported in the linking for the linked language so that the original code does not have to be changed. If the original code has to be changed then old tested and veried code will not be usable in a convenient way. 3

It shall not be much harder to call the linked code than calling code within a language. Interfacing languages can be dicult since calling conventions often differs between compilers. There are two types of linking, static linking and dynamic linking. To understand what happens when linking dierent programming languages and to see the diculties involved a short description of static and dynamic linking will follow. Dierences between linking in Windows and Linux/Unix are also mentioned.

2.1

Static linking

Static linking [22, 9] is the simplest form of linking and the most easy to perform. A static link is made when a number of functions and modules are made into one single executable le when the module is compiled. The execution is usually faster than for dynamic linking but is more inconvenient when many programs uses the same modules, for example the Windows API. If all programs should include all modules they use into one executable le, the program would become huge and it would be dicult to update a function that many program uses. Linux and Microsoft Windows use the same method when linking statically.

2.2

Dynamic linking

In dynamic linking [22, 9] the modules are not included at compile time, instead at execution time. In Windows dynamic linking is accomplished using dynamic link libraries (DLL). In Linux/Unix it is implemented using Shared Objects (SO). The DLL and SO objects are les with pre-compiled code that can be used by any application. The dynamic objects are only loaded when they are needed and are never loaded in multiple instances, though multiple applications can use the same copy of the dynamic objects. Dynamic linking have two load types, run-time and load-time. When loading Windows and Linux API functions load-time is used. Load-time is when a module is loaded into the memory when the program is loaded, just before execution. When run-time loading is used, the DLL is loaded dynamically during execution. The dynamic les have two types of linking, implicit and explicit linking. In implicit linking the operating system handles the linking, while in explicit linking the application handles the linking and the operating system is not involved. Files that uses explicit linking can be of any sort (*.*) but les that use implicit linking must have the le extension DLL for Windows or SO for Linux. The most common is implicit load-time linking. 4

The dynamic linking process is divided into two parts. First, the module that will be linked has to be located. Second, the address of the function in the module must be found. When the two parts are successful the external module can be linked just as if was linked static. Windows and Linux/Unix have dierences in these two steps. In Windows the DLL le can have a complementary library le (LIB le) that contains the functions in the DLL le and the location of the corresponding functions. An application examines the headers to nd the desired module it will link dynamic. In Linux/Unix it is the SO le it self that contains the corresponding information. Two more dierence that exists between Windows and Linux is that Linux can link variables and uses position independent code but Windows does not. Position independent code means that the loaded dynamic library can change place in the memory during runtime. This leads to a more complex architecture but is more exible [22, 9]. The advantages of using dynamic loading are that modules can be updated easily by just replacing a le. All processes using this module are updated automatically. The size in bytes is reduced when several applications can use the same modules. The memory usage is also reduced because multiple applications can use the same copy of the dynamic objects. Dynamic linking also have some disadvantages, when linking does not work it can be hard to nd the errors, because the architecture of a program with dynamic linking is complex [22].

2.3

Tools for generating interfaces to script languages

Creating interfaces for script languages is often a dicult task to do completely by hand. To make it easier special tools can be used to create interfaces between dierent languages. The most common tools are: Simplied Wrapper and Interface Generator (SWIG) Fortran to Python Interface Generator (F2PY) Common Object Request Broker Architecture (CORBA) Component Object Model (COM/DCOM) Previously, in the course Software Development for Technical Systems a special tool, Fortran interface wizard (FIW), was used to create the interfaces between Fortran and Borland Delphi. This tool is also reviewed. Fortran Interface Wizard (FIW) FIW [3] is a tool to make it easier to bind Fortran DLL les to Delphi. In FIW, interfaced subroutines are declared with variables. From this FIW cre5

ates a Delphi import unit and skeleton code in Fortran, which is needed for creating a Fortran DLL. The created Delphi import unit is ready to use but as the name implies the skeleton le(s) needs additional code. The skeleton code contains declaration of variables that are used within the linking to Delphi and implementation to accomplish the linking. The skeleton only needs to be complemented with the code that perform what the subroutine shall do and declaration of local variables. The subroutine(s) are then compiled to a Fortran DLL le that the Delphi import unit links to. The DLL le is dynamically linked when the Delphi project is loaded (explicit load-time is used). This interface also requires a compiler that can build DLL les of Fortran source les. FIW is a Windows-only-solution since Delphi is only available for this platform. Simplied Wrapper and Interface Generator (SWIG) SWIG [20] is a multitool that can generate interfaces to script languages such as Python from C/C++. SWIG can use a header le in C/C++ to create wrapper code that interfaces the script language with the underlying C/C++ code. To use SWIG, a special interface le has to be written by hand, which is used to dene what goes in the wrapper. SWIG is distributed for Windows, Linux and UNIX. SWIG main users are C/C++ developers wanting to provide an interface to a script language. SWIG uses runtime loading. If SWIG is to be used to link Python and Fortran an additional interface generator is necessary for interfacing C/C++ with Fortran. Fortran to Python Interface Generator (F2PY) F2PY [13] is an extension module for Python that generates a direct interface between Fortran and Python. This means that a Fortran module processed by F2PY can create a ready-to-use Python module in a single step. A Python module is a dynamically loadable le that contains the binary compiled Fortran code. All Python applications can use the module that F2PY creates. Disadvantage with F2PY is that it needs ve prerequisites. F2PY uses run-time loading and explicit linking when loading the Python module. Inside the module implicit load-time is used e.g. when the Fortran DLLs are loaded. The code that binds Python with the Fortran code is generated by a signature le created by F2PY. F2PY is platform independent and can be run under Window, Linux and Unix. Common Object Request Broker Architecture (CORBA) CORBA [1, 2, 12] is a middlelayer process in a server/client architecture, which makes objects and applications interact and interoperate. Applications and objects communicate through an Object Request Broker (ORB) that has to be present to run a CORBA process. ORB:s exist for almost all 6

platforms that makes CORBA platform independent. Interfaces in CORBA are dened using an interface denition language (IDL). The purpose of the IDL is to dene the object interfaces in a way that is independent of any programming language, which makes it possible for applications implemented in many dierent languages to interact. Client and server source codes are generated with an IDL compiler that is specic for each programming language. The source code is compiled to an executeable that links to other CORBA applications. CORBA can be used both locally and over networks. If CORBA is used locally, the server and client parts can be made into one binary le, which is very similar to SWIG. For more details see Henning and Vinoski [1]. The disadvantages with CORBA is that there is no straight connection to Fortran and that an IDL le always has to be created. CORBA is made for object oriented programming and is exible and dynamic but this also make it complex. F2PY and SWIG compile code for the linked language, which means that only a specied language can use the created object. CORBA makes the object accessible for all languages. Component Object Model (COM/DCOM) COM/DCOM [2] is a multitool very similar to CORBA and is built in to Windows. A dierence is that DCOM/COM uses a modied IDL. DCOM is used for remote connection and COM for local linking. DCOM/COM is written to work in most operating systems but in practice it almost only works in Windows.

Chapter 3

Scripting languages and computational code


Scripting languages are often used as a tool for gluing components together, which often results in reduced development time. System languages as C/C++ are often compared to scripting languages. System languages are designed to build data structures and algorithms with focus on fast execution in well dened and slowly changing applications, while script languages are designed to glue, handle strings, being easy and fast in development. Script- and system languages complement each other and do not replace each other. Using a script language on top of a low level language makes it more exible. Changes in code are much faster when script languages has less developing time and is easier to understand. Script languages often have good possibilities to create graphical user interfaces, in a way that is easy both for the developer and the user of the nished product, Ousterhout [6]. Scripting language has given up execution speed and strength for getting better reuse of code and higher programmer productivity. Each statement in the source code of a script language contains more instructions for the cpu than a system language. But a scripting language is about 10-20 times slower in execution than a system language, Ousterhout [6]. Execution time for code is getting less important when computers become cheaper and faster in comparison to the cost of a programmer. The main problem for most applications today is not the computing time. Generally, the tasks a script language executes are not the tasks that need to be fast, e.g. it can be waiting for user inputs. Scripting languages are based on built in functions implemented and compiled in a system language, which makes built-in functions almost as fast as system language. When a script language is used the user shall try to use as many of the built-in modules and not to create custom modules that duplicates the built-in modules. A distinguishing feature for scripting languages is that they are typeless to simplify connections between components. System languages are designed 8

for implementing complex components and have a strong degree of typing. In a typeless language variables do not have to be declared before they are used. They can be created on the y and can change type during execution, and are sometimes called dynamic variables. This makes it possible to execute code in script languages at once. Compilation and execution is done in one step. In system languages the entire code rst has to be compiled and then linked before execution. When dynamic variables are used, the debugging procedure between system languages and scripting language dier. System languages check for errors during compilation, and that is impossible for scripting languages as they are typeless. Dynamic variables cannot be checked for errors at compilation because the variables type are not set at this stage. This problem is solved by debugging applications during execution. This result in an error check that is performed as late as possible, which often makes scripting languages more exible. Scripting languages seem as they can allow errors to be undetected but is as safe as the debugging for system languages, Ousterhout [6]. Scripting languages had a breakthrough when the Internet and component frameworks started to expand, graphical user interfaces became popular and script languages started to be good to glue other components. Most programs today have a scripting languages built-in, enabling the user to change the program behavior with custom scripts. Updating programs and using plug-ins are also made easier.

3.1

Python

Python is a programming language created by Guido van Rossum in 1990 and named after the Monty Pythons Flying Circus. Python is best described in programming terms as a modern object-oriented script language. Python has a good mix of engineering language and scripting language, full support for object-oriented programming and a powerful code structure. Python source code is platform independent and can be run on operating systems as Windows, Linux and Unix [4]. As described earlier, script languages can be used to glue components together, which is a distinguishing feature for Python too. This results in better code reuse and fewer rewrites. Python has a very close relation to C/C++ and Java, which makes this languages very easy to use with these languages. Python also has good integration capabilities to most other languages as well e.g. Fortran. Pythons easy code structure makes it straightforward to translate Python to Java and C/C++. This illustrates the exibility of Python as it can be used to glue components together as well as being embedded in other languages. To enhance speed most built-in modules are made in C/C++. Python can also be extended with modules written 9

in C, C++ or in Python. The modules can dene new functions, classes, variables and objects. Python has a large library including functions for Internet access, operating system (OS) integration and user interface. The code structure in Python is simple and that makes it easy to write and understand. Python can also be used as a command line interpreter or in an integrated development environment (IDE) to execute code at once. When the code is executed in Python, the text in the Python le (PY) is parsed and converted to bytecode stored in a PYC-le, which is executed by Pythons virtual machine. This makes the second execution of a PY le faster since the PYC le can be executed immediately since no parsing of the Python le is needed, as illustrated in gure 3.1.

Figure 3.1: Dierence between PY and PYC les To facilitate the development of Python code an IDE can be used, an IDE often has parts that help the developer for writing, editing, testing, debugging and executing code. Komodo 3.1 from Activestate [7] is a professional development environment for dynamic languages, which supports the programmer with autocompletion, highlighting built-in commands and debugging code in the development, see gure 3.2. Komodo also has an interactive shell where single lines of code can be executed.

3.1.1

User Interfaces for Python

The user interface is the graphical part of the application that communicates with the user. Often this is used to dene input data and view results. Python has a number of dierent graphical user interface (GUI) toolkits, such as Tkinter and wxPython [23]. More toolkits can be found on Pythons GUI section [15]. Tkinter is built in to Python that makes it de facto standard GUI toolkit for Python. The same Tkinter source code can be used on all platforms supporting Python. wxPython is another good toolkit that could have been the main one if Tkinter was not rst. wxPython is as simple and easy to use as Tkinter but contains more graphical objects. wxPythons two disadvantages are that it is not built-in to Python and that it can be hard to run on all platforms even though it said to be platform independent [16]. The graphical objects in a GUI toolkit are often called Widgets. The widgets that make Tkinter (Python) better than other toolkits are the text10

Figure 3.2: Komodo IDE with explanations and the canvas widgets [4]. Using these widgets text, lines or pictures can be added and in an easy way deleted by setting tags (a group of objects) to dierent objects. Python also support many other functions for graphical interfaces. Most types of applications can be developed. GUI builders A large amount of source code is often needed to implement a user interface. To make this task easier a program can be used, which automatically generates source code for the graphical parts of a program e.g a button. This sort of program is called a GUI-builder. Often objects/widgets can be added to a window using drag and drop, see gure 3.3. The GUI builder can also change the attributes for the created widgets eliminating editing in the source code. The code for the graphical parts of a program that needs to be written manually is the event code. The event code can be code that describes what happens if a button is pressed or code for loading values into entries. Komodo 3.1 that is described earlier also includes a GUI builder, as shown in gure 3.3. One disadvantage with the Komodo GUI-builder environment is that Python is not the best supported language. Some functions does not work at all, the documentation is also lacking in many areas. Komodo GUI builder generates two les. One read only le, which contains the graphical commands for the widgets and one, which can be edited that contains the event code and other settings that are added manually. To understand the gener11

Figure 3.3: Komodo GUI builder.

ated code and to add own code, the user must have knowledge about object oriented programming including the self variable and inheriting as the two generated les are built up with classes. The preferences that can be change in the GUI builder will also easily confuse. All preferences that can be edited does not make any dierence or does not work. Despite some weaknesses Komodo is an good GUI builder and reduces the time to implement a graphical user interface. Komodo is available for Linux, Microsoft Windows and Solaris [7].

3.1.2

Computational environment

Python has no built-in support for matrices and advanced mathematical computations. To handle this sort of functions in Python, additional modules have to be used. There are two main modules available, Numarray and Numeric [11]. Numeric is the predecessor to Numarray and they are very similar except that Numarray is faster for larger systems. They support both matrices and advanced computation, such as solving linear equation systems. Numeric and numarray creates a MATLAB [10] like environment in Python with similar syntax and functionality. The preferred module is Numarray, but Numeric is still frequently used. None of the modules are included in the Python distribution and they have to be installed separately. 12

3.2

Fortran

Fortran [8, 3] was developed in the 1950, since then new standards has been developed and the latest is Fortran 95, Fortran 2003 is under development. All new standards are backward compatible with the three latest standards. Since Fortran is standardized it is a platform independent language, so a program written in Fortran can be compiled on any platform having a Fortran compiler. Fortran is mostly used by engineers and researchers, as it is a fast system language that is often used in software requiring fast numerical calculations. A large amount of well established numerical code is written in Fortran. The main disadvantage with Fortran is that it can be complex and does not support object orientated programming. Fortran is about 15-20 times faster than Python. This is due to the fact that Fortran compiles the entire code to machine code executing directly on the target processor.

3.3

Tools used in this work

Python was chosen as the script language in this work. The main reasons for this are that it is an easy-to-learn language, integrates well with Fortran and supports GUI development. The graphical user interfaces are implemented with the Tkinter toolkit as it is built-in to Python. As interface generation tool F2PY was chosen after evaluating the dierent interface generation tools available. F2PY creates an interface to Fortran in a simple single step. The SWIG interface generator is mostly used to generate interfaces for C/C++. Generating Fortran interfaces would require extra C layer, which makes it less useful. Almost a new programming language has to be learned if CORBA or DCOM/COM is used. Numeric is used for matrices that are passed between Fortran and Python.

3.4

Fortran to Python Interface Generator (F2PY)

F2PY [13] is an extension module to Python that make it possible to link Fortran source code to Python. F2PY creates Python C/API modules from signature les. The signature les are made by hand or generated automatically with F2PY from Fortran source code. The signature les contains information about functions and variables in the Fortran source code. From the signature les the bindings between Python and Fortran functions can be built. F2PY is simple to use because binary Python modules can be built in a single step from Fortran source. The interface is generated without loosing any advantages in Fortran as the Python modules are binary. The main features for F2PY are: Fortran 77/90/95 functions, F90/95 modules and C function are supported. 13

Scalar numbers Numeric arrays Numarray arrays Strings Dictionaries Lists Tuples

Supported in F2PY yes yes yes yes no yes** yes**

Passed as reference no yes* no no no no no

Output yes yes no yes no no no

Table 3.1: Overview of supported variables in F2PY. * The variables are only passed as reference if the arrays are set to column major storage and declared as an array in Fortran. ** Lists and Tuples are converted to numeric variables in F2PY and are not recommended to use with F2PY. Functions and data in Python can be accessed from modules created in F2PY with a callback function. Arguments in linked functions can be optional, required or hidden and dependencies between arguments are solved automatically. F2PY detects automatically if an array that is sent to a F2PY created module is of column major storage or row major storage.

3.4.1

Creating a Python module

To create a Python module some issues have to be considered. Even though F2PY detects what sort of storage an array has, this is the main problem when interfacing Fortran and Python. The problem is that matrices in Fortran and Python are stored dierently in memory. Python uses row major storage (C contiguous) and Fortran use column major storage (F contiguous). The input to F2PY is solved automatically but returned arrays from Fortran are always column major storage. This introduces some complications in Python, as described later. An array of Numeric type stored in column major storage is passed by reference between Python and Fortran. If the variable is not stored in the correct format and is of the right variable type, the variable will be copied before function call. Passing scalars variables as references requires the scalars to be declared as an array with length one, the default is to pass scalars by value. Python variables also have to be declared with the same type as the corresponding variable in Fortran if they should be passed by reference. For example a double variable in Fortran needs to be linked with a Python variable declared as a double. Numarray arrays cannot be passed by reference to F2PY created modules. An overview of variables supported and how they are passed is shown in table 3.1. Changing a Python array to column major storage can be done by transposing or using the as_column_major_storage(<array>) function, which 14

is built-in to all F2PY created modules. The latter function converts the matrix to column major storage without ipping the rows and columns as transpose does. With both these functions some important properties of the matrices are lost, therefore the returned matrices must be treated carefully in Python. E.g rows or columns that are not next to each other in a matrix cannot be change at the same time, partial indices cant be used. Both Numeric and Numarray has a function copy, which creates a exact copy of a F-contiguous array but it is C-contiguous. Special F2PY attributes controlling the behavior of variables can be set in the signature le or directly in the Fortran source code. Adding these attributes does not have any disadvantages for the Fortran code. The most common attributes are: In, which is the default setting if no other attributes are set to a variable. This means that a variable is a required input in a subroutine or function. Out, which is set to a variable if it is to be returned to Python. If a variable is both an input and output variable in, out is used. Copy, if a Numeric variable that is Fortran contiguous is used it is linked as a reference. If this Numeric variable does not want to be passed as a reference, copy can be used. C, denes the array variable as row major storage. It is not recommended to use since a Numeric C-contiguous array will be passed as reference, which results that position [2,2] of the matrix in Python does not correspond to position [2,2] in Fortran. This is confusing and makes the variable less usable. Attributes are added after the normal Fortran declaration of the variable by using the intent F2PY keyword, as shown in the following code.
! variable declaration r e a l ( kind =8) : : e p r o p ( 6 , ) ! adding a t t r i b u t e ! f2py i n t e n t ( in , out ) eprop

F2PY keywords are declared in Fortran as comments, so that they do not interfere with the compiler. All variables that are given an attribute are declared in the subroutines header. More detailed documentation can be found on F2PYs homepage [13]. 15

There are as well some minor Fortran features not supported functions in F2PY. F2PY has problems compiling les with the extension .f95 but les with the extension .f, .f77 or f90 are supported. The accuracy of a variable cannot be set by a parameter, it has to be set with a value, e.g. kind=8. Before starting to use F2PY some prerequisites have to be installed. They are listed below. Python Numpy (Numeric), Matrix handling Numarray (optional), Matrix handling SciPy, Compiler handling Fortran compiler C compiler The C and Fortran compilers should preferably be from the same vendor. This is specially important for Windows since the object le formats dier between compilers. In Linux any Fortran and C compilers can be used in any combination. F2PY supports a number of major Fortran and C compilers as listed in F2PYs documentation [13]. When all the prerequisites are installed and congured properly F2PY is easy to use. To compile the Fortran les to Python modules, F2PY is called with the command F2PY in the command prompt in Windows or Linux. To build a Python module in a single step the following command is used.
f2py -c -m <Name Python module> <Fortran files>

Additional options can be set to F2PY in the same command. The reader is referred to F2PYs documentation [13] for more information. The example below illustrates a session of using F2PY from the command line.
W:\f2pyGUI>f2py -c -m testmodule hello.f90 numpy_info: FOUND: define_macros = [(NUMERIC_VERSION, "\\"23.1\\"")] include_dirs = [C:\\Python23\\include] running build running config_fc running build_src building extension "testmodule" sources . . .

16

. Removing build directory c:\docume~1\bmxjmr\locals~1\temp\tmpsb2max W:\f2pyGUI>


A The modules are also automatically documented with L TEX in F2PY. To make it easier to use F2PY a GUI is developed in Python for F2PY. The application is described in section 4.2.

3.4.2

Using F2PY generated modules in Python

Using F2PY generated modules in Python is done in the same way as normal Python modules. To illustrate how to use F2PY two examples are given. Example 1 Example 1 shows very basic commands for F2PY. A Fortran module test is located in a le file.f90 and this le is compiled in F2PY and the Python module module.pyd in Windows or module.so in Linux is created. The Fortran code is presented rst and then commands in a Python interpreter with results. The # or ! signs is a comment. Fortran code
! F i l e module . f 9 0 subroutine t e s t ( a ) integer : : a p r i n t , H e l l o Python p r i n t , a= , a end s u b r o u t i n e t e s t ! End f i l e module . f 9 0

The Fortran code is compiled with F2PY by giving the following command in Windows command prompt.
f2py -c -m module file.f90

Python interpreter To import the F2PY created module module.pyd the command import is used. 17

>>> import module

The help documentation is printed on the screen with the following command.
>>> module . t e s t . doc

t e s t Function signature : test (a) Required arguments : a : input int

The instructions in the documentation shows how to use the module, the module requires one input argument. The module is executed underneath.
>>> module . t e s t ( 5 ) H e l l o Python a = 5

Example 2 This example illustrates how Numeric arrays are used with F2PY created modules. The example shows how a Numeric array is handled when interfaced as a reference and as a copy. It also describes how a return-variable is given an attribute. Fortran code
! F i l e test2 . f90 subroutine t e s t ( a , b , c ) r e a l ( kind =8) : : a ( 2 , ) , b , c ( 2 , ) ! f2py ! f2py i n t e n t ( out ) b i n t e n t ( in , out ) a , c

a ( 1 , 2 )=a ( 1 , 2 ) +10 b=a ( 1 , 2 ) c ( 1 , 2 )=c ( 1 , 2 ) +10 end s u b r o u t i n e t e s t ! End f i l e t e s t 2 . f 9 0

18

Compiling Fortran code to Python module:


f2py -c -m test2 test2.f90

Python interpreter Importing Numeric module for matrix support.


>>> from Numeric import

Importing F2PY generated module.


>>> import t e s t 2

Print the documentation, which shows that there are two required arguments (a,c) and three returned objects (a,b,c).
>>> p r i n t t e s t 2 . t e s t . doc

t e s t Function signature : a , b , c = test (a , c) Required arguments : a : i n p u t rank 2 a r r a y ( d ) w i t h bounds (2 ,) c : i n p u t rank 2 a r r a y ( d ) w i t h bounds (2 ,) Return o b j e c t s : a : rank 2 a r r a y ( d ) w i t h bounds ( 2 , ) b : float c : rank 2 a r r a y ( d ) w i t h bounds ( 2 , )

Creates variable a that shall be a matrix with two rows and the number of columns is dened by the user. The d means that it is a variable of type double. The variable is transformed to be column major storage.
>>> a=t e s t 2 . a s c o l u m n m a j o r s t o r a g e ( a r r a y ( ( ( 1 , 2 ) ,(2 ,3) ) , d ) )

Creates the array c that looks exactly as the variable a except that it is row major storage array.
>>> c=a r r a y ( ( ( 1 , 2 ) , ( 2 , 3 ) ) , d )

The function test is executed with the input variables a and c, the returned variables are stored in A,B and C.

19

>>> A , B , C=t e s t 2 . t e s t ( a , c )

Variable A is printed, this is the original a value, which is returned and changed.
>>> p r i n t A= ,A A= [[ [

1. 2.

12.] 3.]]

Variable B is printed, this variable shows how to set an attribute to a variable, which is only output.
>>> p r i n t B= ,B B= 12.0

Variable C is printed, This is the original c value that is returned and changed.
>>> p r i n t C= ,C C= [[ [

1. 2.

12.] 3.]]

Variable a is printed, it is passed as a reference since it is column major storage and that is the reason why it is change from the original value.
>>> p r i n t a= , a a= [[ [

1. 2.

12.] 3.]]

Variable c is printed, it is passed as a copy since it is not column major storage, this result in that it is not changed from the original value.
>>> p r i n t c= , c c= [[ 1. [ 2.

2.] 3.]]

20

Chapter 4

Application cases
Python, Fortran and F2PY are evaluated in combination to so see if they fulll the demands computational applications has both from the user and in a developers perspective. Test application cases are implemented to evaluate this combination of programming languages, where both diculties and possibilities for Python and F2PY are mentioned. Fortran is not covered extensively as there is nearly no change in Fortran from the existing course layout of Software Development for Technical Systems. The creation and structuring of the test applications are also described. Two applications cases are studied. The larger application case is a two dimensional nite bar element program (2D Truss). The smaller application is a graphical user interface for F2PY. The latter application illustrates how Python can be used to implement an user interface to an application rapidly and be used as a good gluing language. All Python code is generated with help from the books by Mark Lutz & David Ascher [4, 5] and the Python.org web site [14] if nothing else is written.

4.1

2D Truss

2D Truss is a two dimensional nite element truss program where all elements consist of bar elements, see gure 4.1. A nite element solver implemented in Fortran is used for the computations, the graphical user interface (GUI) is implemented in Python and F2PY is used to implement the interface between Fortran and Python. In the existing course of Software Development for Technical Systems there is an assignment that is very similar to 2D Truss. This assignment is used as a skeleton for 2D Truss and can be found on Structural Mechanics homepage [21]. The writer who has taken the existing course has there developed the application in the assignment, the computational part will be partly reused in 2D Truss. A rough layout for a nite element computational 21

Figure 4.1: Bar element with properties program and the requirements for 2D Truss are described in the assignment. In the list below the rough layout of a computational application is show. After a introduction to 2D Truss a quick review will be given for the existing layout of the assignment. Give input data in text form and/or graphically. Perform calculations. Presentation of result in text form and graphically. 2D Truss have goals for each item in the list above and the goals are taken from the existing assignment and are described underneath. Figure 4.2 shows an example how the application will look like when it is nished. Input data: The input data is set in the graphical part and gives the user the possibility to create elements, dene element topology, set nodal forces and set prescribed displacement of nodes. The element properties are presented in gure 4.1, which shows a bar element for a plane truss. Before calculation the geometry can be drawn to verify the input. Calculation: Calculations are made with a banded nite element solver. The calculations also include assembling to stiness matrix and force vector. Result: The results are presented both in text form and graphically. The results in text form are presented in a result le and contains reaction forces in nodes, displacement of nodes and normal forces in elements. The result le can be viewed in 2D Truss. Normal forces in elements and displacement of nodes are also presented graphically in combination with the geometry of the model. 22

Other requirements: 2D Truss also follows the requirements to be able to save, save as, open and create new models.

Figure 4.2: Main window in 2D Truss with displacement and element number drawn for a test model.

4.1.1

Quick review of former course layout

In former courses the goal was to create a program with the same structure and requirements as the program described above. The layout was constructed so that Fortran was used for computational code and Borland Delphi is used for the user interface. The interface between Fortran and Delphi is made with help from Fortran Interface Wizard (FIW) and a Fortran Compiler. First, the computational part in Fortran is developed. It consists of functions to create element matrices, a boundary vector, assemble element matrices to a global stiness matrix and to create a force vector. These vectors and matrices generate a system of linear equations, which is solved with a nite element solver that can handle boundary conditions. The results from the solver are displacements of elements, from which the normal force in each element can be calculated. To be able to test and verity the calculations, two functions are created, one to read input les and one to write a result le. 23

The Fortran Interface Wizard is used to create an interface between Fortran and Delphi. FIW is described in section 2.3. Three main Fortran subroutines are interfaced: read size of the problem, read input data and execute the solver. Delphi has to read the size of the problem before all input data can be read because the matrices in Delphi have to be allocated before the cells can be lled. The three main subroutines are not run in a single step as the user shall have the ability to make changes in the input data before a calculation is performed. The read and write routines could have been implemented in Delphi but in order not to rewrite any code, Fortran continued to implement these functions. To build the graphical user interface, Borland Delphis GUI builder is used. When the nished application built with the GUI builder and started, a main window appears. This window shows the menu and graphics of a created model. The input data and results of a model are stored in a matrix and vector controlled by a unit Model. The input data is edited in sub windows that are reached from the menu. If the size of a model is changed, a function that resizes the matrix and vectors without loosing the stored values is called and all new cells are set to zero. If the changes needs to be saved a save command is found in the menu. The save command creates a input le that follows the input data manual that Fortran uses when reading input data. To perform a calculation, calculate is chosen in the menu. Then the input data in the matrices and vectors are passed straight to the Fortran DLL. The result from the calculations is returned both in arrays for the graphical presentation and in a text le to show the result in numbers. A unit called ModelDraw controls the graphical presentation in the canvas of the main window. All sub windows have one unit each that handles event code and build up the windows. This assignment shows that Delphi has a simple structure that is easy to follow. In the project, no object oriented programming was used, which makes the application less exible and complex if larger applications are built. Delphi GUI builder is an advanced builder with many built-in preferences and all objects can easily be linked to an event. The application made with Delphi looks almost the same as the application in gure 4.2.

4.1.2

Interfacing Python with Fortran

The prerequisite and the review from the former course assignment makes it possible to start to create a more detailed outline for 2D Truss. The outline for the computational part is made rst since most of the Fortran source code will be reused from the Fortran-Delphi project described above. The graphical interface is not dependent on the structure of the computational part but the GUI is dependent on the computational part. The computational part of Fortran (FE-solver) denes the output and input variables (arguments) for the subroutine that is called from Python. 24

To continue further it has to be decided how the input data (input to FEsolver) for a model is stored and treated in the Python part of 2D Truss. The FE-solver requirements are matrices, vectors and scalars. Either they are stored in Python exactly as the FE-solver requires them or the input data is stored in any form and the required variables are created just before calculation. The rst variant that is used in the existing course is not possible to use conveniently, as Python does not have a variable type, which can change size in combination with saving the old values in the same cells and set zeros to new cells. Because Python has good support for object orientated programming it can handle the input data in instances of classes. From the instances matrices, vectors and scalars are create just before computation. A consequence with the latter method is that Python will read the input data les. Python has a good function cpickle to save instances of a class to le. The latter method is used in 2D Truss. The routines in Fortran for computation and writing the result to a result le are reused. FE-solver returns displacement and normal forces to Python for graphical presentation. Input data to 2D Truss are described with three classes: model, element and node. Classes The classes are implemented so an instance of the model object is created for each opened project in 2D Truss. The model class have methods for adding and removing instances of element and node objects (aggregates), see gure 4.3. An example of a class implementation is shown in a listing after the three classes are described.

Figure 4.3: Structure of classes in 2D Truss

Model An instance of the model class handles most of the properties of a structure/model such as the names for the input data les and result les. Lists with element and nodes are stored and the instance also contains the number of elements, nodes, nodal forces and prescribed node values. After calculations the results that are used in the graphical presentation are stored in arrays. Functions to set and retrieve variables are also implemented. 25

Node An instance of the node class contains the variables, number of degrees of freedom, x and y coordinates of the node, nodal forces and prescribed node values. To control the variables, functions are implemented to set values and get values of the variables. When an instance of the node class is created, the number of degrees of freedoms a node has can be dened. The default value is set to two degrees of freedom and is not changed in this application, as other functions does not support other than two degrees of freedom.

Element The element class implements the properties of an element, which are area, E-modulus, and nodes. The nodes contains the x and y coordinates so the elements dene their size and position in terms of nodes.
# C l a s s t h a t h a n d l e s b a r e l e m e n t w i t h two dimensions

class element : # def When an i n s t a n c e i s c r e a t e d init ( s e l f , n1 , n2 ) : s e l f . n o d e s =[n1 , n2 ] #Nodes s e l f . E=0. #Emoduls s e l f . A= 0 . #Area R e t u r n s t h e a r e a and t h e emodulus

def g e t p r o p ( s e l f ) : return [ s e l f . E , s e l f .A] # Returns the nodes

def g e t n o d e s ( s e l f ) : return s e l f . nodes # Set p r o p e r t i e s

def s e t p r o p ( s e l f , Emodule , Area ) : s e l f . E=Emodule s e l f . A=Area # Set nodes of the element

def s e t n o d e s ( s e l f , n1 , n2 ) : s e l f . n o d e s =[n1 , n2 ]

26

Implementing the Fortran Python module The decision how a project handles input data makes it possible to change the Fortran source code so it can be reused. After the Fortran source code is modied to suit F2PY it can be run in F2PY and tested. The Fortran solver is built with reused parts of the Fortran code from the former course. A main module calcprog is created that includes a subroutine execute, which is the subroutine that interfaces to Python. Execute calls the other Fortran sub modules that implements the components part of the application, illustrated in gure 4.4. As the subroutines are tested and veried in the former assignment of Software Development for Technical Systems this results in that only the new main module has to be tested and veried. It is easier to manage, update and nd errors when the Fortran DLL is structured as in gure 4.4. The Submodule barelement creates element matrices and force vectors, which are assembled to a global stiness matrix and force vector. Barelement also calculates the bandwidth of the global stiness matrix. Solve solves the linear equation system and barelement calculates the normal forces in the elements from the displacement that are given from the solver. As a last operation outputfile creates the result le. Main module calcprog is shown in appendix B.1.

Figure 4.4: Structure of Fortran DLL solvepro.pyd The interfaced variables from Python to calcprog does not need any F2PY attributes, since the arrays in the interface are Numeric variables and converted to column major storage so they will be passed as references. Displacement and normal forces arrays are returned from the Fortran DLL are created in Python before the calculation and then passed as reference, which make them change to the result automatically. The returned arrays in Python do not impose any diculties as they are Fortran contiguous and can be treated as vectors and not matrices since they are rank-1 arrays. Rank-1 arrays of column major storages do not aect the properties of the arrays. The only code that is changed in the Fortran code before the compilation in F2PY is the accuracy of a variable. The interface is shown below where 27

the header to FE-solver is shown and the entire module in appendix B.1. Header of solver in Fortran
s u b r o u t i n e e x e c u t e ( n e l , neq , n n l , npv , eprop , e d o f , f , bc , b , eforces , outfile , ierr , displace ) ! D e c l a r a t i o n o f e x p o r t e d v a r i a b l e s . i m p l i c i t none integer : : nel i n t e g e r : : neq integer : : nnl i n t e g e r : : npv r e a l ( kind =8) : : e p r o p ( 6 , ) integer : : edof (4 ,) r e a l ( kind =8) : : f ( ) r e a l ( kind =8) : : bc ( ) integer : : b () r e a l ( kind =8) : : e f o r c e s ( ) character (255) : : o u t f i l e integer : : i e r r (1) r e a l ( kind =8) : : d i s p l a c e ( )

To call FE-solver in Python the following procedure is used, the complete module can be found in appendix A.3. The name of the PYD le is solvepro and then the subroutine execute is in a module calcprog. Before the FEsolver is called from Python the necessary variables are constructed with a function createArrays from the input data in the instances of model, node and element. Python call procedure
# c r e a t e s t h e a r r a y s wh ich a r e l i n k e d .

[ n e l , neq , n n l , npv , eprop , e d o f , f , bc , b , i e r r ]= createArrays ( projekt ) # s e t s t h e r e t u r n e d v e c t o r s t o z e r o and g e t them from t h e c l a s s o b j e c t

p r o j e k t . setDispAndEforceToZeroAndSetSize () d i s p , e f o r c e s=p r o j e k t . g e t D i s p A n d E f o r c e s ( ) # C a l l s e x e c u t e i n t h e module c a l c p r o g i n t h e f i l e s o l v e p r o . pyd t o p e r f o r m t h e c a l c u l a t i o n s

s o l v e p r o . c a l c p r o g . e x e c u t e ( n e l , neq , n n l , npv , eprop , e d o f , f , bc , b , e f o r c e s , o u t f i l e , i e r r , d i s p )

28

# # #

i e r r i s a e r r o r f l a g i f the probelm i s nonpositive definit o u t f i l e i s t h e name o f t h e r e s u l t f i l e e f o r c e s and d i s p a r e r e t u r n e d a r r a y s and t h e r e s t are input v a r i a b l e s

createArrays is shown in the listing below. Transpose is used to convert the matrices to column major storage and is done in order not to depend on the F2PY command as_column_major_storage(<array>), which is only available if a F2PY module is imported. When doing this, the matrices have to be constructed transposed to the matrices that will be linked to Fortran. CreateArrays
def c r e a t e A r r a y s ( p r o j e k t ) : v a r=p r o j e k t . g e t p r o b l e m i n f o ( ) n e l=v a r [ 0 ] neq=v a r [ 1 ] 2 n n l=v a r [ 2 ] npv=v a r [ 3 ] # Creates the a r r a y s with zeros

i e r r =a r r a y ( 0 ) e p r o p=z e r o s ( ( n e l , 6 ) , d ) e d o f=z e r o s ( ( n e l , 4 ) , l ) f=z e r o s ( neq , d ) b=z e r o s ( neq , l ) bc=z e r o s ( neq , d ) # F i l l the a r r a y s with i n f o r m a t i o n about the p r o b l e m a f t e r a p a t t e r from a i n d a t a manual f o r the f o r t r a n s o l v e r

for i in xrange ( nel ) : e=p r o j e k t . g e t e l e m e n t ( i ) n1=p r o j e k t . g e t n o d e ( e . g e t n o d e s ( ) [ 0 ] 1 ) n2=p r o j e k t . g e t n o d e ( e . g e t n o d e s ( ) [ 1 ] 1 ) e p r o p e l =[ e . g e t p r o p ( ) [ 1 ] , e . g e t p r o p ( ) [ 0 ] , n1 . g e t c o o r d ( ) [ 0 ] , n1 . g e t c o o r d ( ) [ 1 ] , n2 . g e t c o o r d ( ) [ 0 ] , n2 . g e t c o o r d ( ) [ 1 ] ] e d o f e l =[ n1 . g e t d o f ( ) [ 0 ] , n1 . g e t d o f ( ) [ 1 ] , n2 . g e t d o f ( ) [ 0 ] , n2 . g e t d o f ( ) [ 1 ] ] e p r o p [ i ]= e p r o p e l

29

e d o f [ i ]= e d o f e l for i in xrange ( var [ 1 ] ) : n=p r o j e k t . g e t n o d e ( i ) f [ i 2]= n . g e t n o d e f o r c e s ( ) [ 0 ] f [ i 2+1]=n . g e t n o d e f o r c e s ( ) [ 1 ] b [ i 2]= n . g e t b ( ) [ 0 ] b [ i 2+1]=n . g e t b ( ) [ 1 ] bc [ i 2]= n . g e t b c ( ) [ 0 ] bc [ i 2+1]=n . g e t b c ( ) [ 1 ] # # End f i l l i n g t h e a r r a y s w i t h i n d a t a T r a n s p o s e t h e a r r a y s t o s t o r e them c o l u m n w i s e l i k e f o r t r a n n e e d s and n o t r o w w i s e l i k e p y t h o n makes by d e f a u l t

e p r o p=t r a n s p o s e ( e p r o p ) e d o f=t r a n s p o s e ( e d o f ) r e t u r n n e l , neq , n n l , npv , eprop , e d o f , f , bc , b , i e r r

Because the input data is layout in the correct structure for the Fortran module, it can now be tested. If F2PY runs correctly it is now possible to compile the Fortran source code to a Python module in one single step.

4.1.3

User interface implementation

The main frame in the graphic part is used as a starting point for 2D Truss user interface and is implemented rst. All windows and modules are implemented with approximately the same structure as in the assignment in the former course. The structure for 2D Truss is shown in gure 4.5. The user interface modules are built with Komodo 3.0 GUI builder.

Figure 4.5: Structure of GUI for 2D Truss 30

Windows and Modules In the main frame the drawing area and the menu are displayed, they are shown in gure 4.2. The menu is built with four main drop down menus: le, input data, calculations and output data. The sub items to each main menu can be seen in gure 4.6. All sub items of the le menu are handled by the module base.

Figure 4.6: Menu in 2D Truss

Module base and le menu Module base contains the model class, createArrays function, execute function(perform a calculation) and the functions in the le menu. The class model, createArrays and execute are described earlier. The new option in the menu creates a new instance of the model object. Save calls a module cpickle in Python, which is a module that can save an instance of a class to a le [14]. In 2D Truss the instance of the class model is saved and since it contains all the instances of element and node they are saved as well. Open also uses cpickle to open the saved instance again. Save as ... and Open open a built-in module tkFileDialog that provides interfaces to native le dialogues, Secret Labs internet site [19] has good documentation. Input data menu In this menu the properties for the model can be changed or set. All options are opened in a new window. Sub windows that handles input data use the same ow of event when the input data is set or changed, see gure 4.7. The gure also shows the window where the element properties are shown and can be changed. The code for the element properties window is presented in appendices A.5 & A.6. All input sub windows are describe below. Model information This window shows number of elements, number of nodes, number of nodal forces and number prescribed node values in the project. Nothing is set in this window, the purpose is to verify data. Element properties From this window the area, E-modulus, start and end node can be set for each element in the structure. Number of elements is also set here. 31

Figure 4.7: The gure to the left shows a typical input data window in 2D Truss, The gure to the right describes how an input data window is implemented for changing input data. Node properties From this window the properties for the nodes can be set or changed. The entries are number of nodes, x coordinate and y coordinate. The windows also shows which degrees of freedom that belongs to the node and are set automatically. Nodal Forces This is the window for setting nodal forces for each degree of freedom, one horizontal and one vertical degree of freedom for each node. The default value is zero. Prescribed node values The same as for nodal forces but here the displacement for each degree of freedom is set. A checkbox is ticked if the node is prescribed or not. Calculations menu Once a complete model has been built or opened it can be solved by choosing Calculate in the Calculations menu. Output data menu This is the last menu option. In this menu the result le can be shown in a new window or a graphical presentation of the model can be viewed in the drawing area, where deformations and normal forces can be shown graphically in combination with the model. The drawings are handled in a module modeldraw. Result le window The result le is shown in a text canvas in a new window. Module Modeldraw The module modeldraw handles the drawing of the geometry and results in the drawing area, implemented using a Canvas widget. The Canvas is one of the strong parts in Tkinter, see gure 4.2. With 32

only a few lines of instructions, a complex geometry can be drawn, including lines with thickness and arrowheads, Secret Labs homepage [19] provides good documentation. The advanced drawing functions of the Canvas widget is illustrated in the code below, in appendix A.4 the complete module modeldraw is shown.
# If t e n s i l e s t r e s s in a bar element

i f f o r c e [ i ] > 0: c a n v a s M a i n . c r e a t e l i n e ( xd1 , yd1 , xd2 , yd2 , a r r o w= b o t h , t a g= a r r o w , f i l l = b l u e , a r r o w s h a p e =(8 ,10 ,3) ) # I f compressive s t r e s s in a bar element

else : c a n v a s M a i n . c r e a t e l i n e ( xd1 , yd1 , xd2 , yd2 , a r r o w= b o t h , t a g= a r r o w , f i l l = r e d , a r r o w s h a p e =( 8, 10, 5) )

Figure 4.8: Normal forces drawn in 2D Truss In the listing above two commands for drawing lines are shown. The option arrow is only written if arrows are wanted, fill means what color the line has. Arrowshape sets the shape of the arrow, a minus makes the arrow change direction, see gure 4.8 Before the geometry and results can be drawn a translation has to be done of the geometry as the global coordinate system for the FE-model is dierent from the canvas coordinate system. The structure also has to be scaled to t the window. The canvas coordinate system is dened from the upper left corner with the x-axis going right and the y -axis going downwards and the FE system is dened as in gure 4.1. To translate the coordinate system two functions are implemented, coordvalues and maxminXY. MaxminXY 33

nds the size of the structure and the window to draw in so a ratio can be calculated, which is set to use as much of the window that is possible. Coordvalues nds a function with help from the ratio, which can translate and scale FE coordinates to the canvas coordinates. The structure, displacement and normal forces are drawn in the canvas with three dierent functions. If displacement or normal forces are drawn the geometry function is called rst to draw the geometry. When a drawing option is called in the menu, a draw function in the mainframe module is rst called. This draw function then calls the functions in modeldraw. Tkinters canvas has a useful option that allows each object that is drawn to get a tag. In 2D Truss the drawn objects for element numbers, node numbers, nodal forces and prescribed node values have a tag each so that they can easily be deleted or drawn when the checkbuttons in the mainframe are ticked or unticked eliminating the need to redraw the whole gure. This option is available for all drawings in 2D Truss. The following code is extracted from the DrawGeometry function in the modeldraw module, which calls functions to draw if the checkbuttons are ticked.
# Draws e l e m e n t n u m b e r s i f t h e c h e c k b u t t o n i s filled

i f i n t ( r o o t . g e t v a r ( showElNr ) ) ==1: p r i n t E l e m e n t N r ( canvasMain , p r o j e k t ) # Draws nodenumbers i f t h e c h e c k b u t t o n i s filled

i f i n t ( r o o t . g e t v a r ( showNodeNr ) ) ==1: p r i n t N o d e N r ( canvasMain ) # Draws n o d a l f o r c e s i f t h e c h e c k b u t t o n i s filled

i f i n t ( r o o t . g e t v a r ( showNodeForce ) ) ==1: p r i n t N o d e F o r c e ( canvasMain , p r o j e k t ) # Draws p r e s c r i b d e d o f i f t h e c h e c k b u t t o n i s filled

i f i n t ( r o o t . g e t v a r ( showPreNodes ) ) ==1: p r i n t P r e N o d e ( canvasMain , p r o j e k t )

If the window that contains the drawing area is resized the drawing area has to be resized and the objects in the drawing area redrawn. In the following listing the method for doing this is shown. This example is taken from initialization of the main window where the drawing area is created. Canmain is the name of the instance of the Canvas widget (the drawing area) and draw is the drawing function in the program. This event happens 34

if something is changed to Canmain, not only if the drawing area is resized.


def init ( self , root ) : . . s e l f . canmain . b i n d ( < C o n f i g u r e > , s e l f . draw ) . .

Another good characteristic of the canvas is that dierent objects can be moved forward and backwards on the screen.

4.1.4

Final outline for 2D Truss

The nal structure of the application 2D Truss is presented in gure 4.9. All events in 2D Truss starts from the main frame and are initiated by the user. Figure 4.9 also illustrates the ow of events. The numbers represents the main tasks of the application.

Figure 4.9: How 2D Truss works 1. When a model/project is saved, opened, saved as.. or a new is created, a function in module base is called, which retrieves or set the input data in the classes. Everything is set to zero when a new project is created. 2. When a input data window is opened input data is collected from the model instance, which in the other hand collect input data about elements and nodes from from the instances in the node and element 35

lists. If input data is changed by the user input data is sent in the other direction. 3. Calculations are performed by the Fortran computational module were a result le is created and displacements and normal forces of the structure are sent to the model instance. The input data is collected and transformed to arrays in base before the computations are performed. 4. When results are chosen to be shown graphically the canvas retrieves all input data for the structure from the model, element and node instances. 5. The result le is included in a text canvas, which is opened in a sub window when that menu option i chosen. 2D Truss has been tested and veried with a application example, see gures 4.10 and 4.11.

4.1.5

Python help and hints

Building the graphical user interface brings up a number of diculties that are worth mentioning in this section. Some diculties are introduce when linking frames/windows that are created with Komodo. All frames or windows in an application can rst be built up and run separately with Komodo. At some stage in a project one window is linked to another window through a button or a menu. To implement this, a function that is run when the window is created has to be added to the sub window. This function also make it possible to setup variables and call functions when the window creates. After this is added the window cannot be run separately, if not a complementary if statement is added, which disables the initialize functions described above. In the listing below it is show how a new window is opened and then the extra functions that are added to the sub windows source code. In appendices A.2 & A.5 the entire les are shown.
# Open a new window t o s e t e l e m e n t p r o p e r t i e s , code from t h e main window

def f r m E l e m e n t P r o p ( s e l f ) : import e l e m e n t p r o p window=T o p l e v e l ( ) e l e m e n t p r o p . CustomElementprop ( window , p r o j e k t ) window . g r a b s e t ( ) window . f o c u s s e t ( ) window . w a i t w i n d o w ( )

36

Figure 4.10: Application example in 2D Truss 37

Figure 4.11: Result for application example in 2D Truss 38

# #

E x t r a c t from e l e m e n t p r o p e r t i e s window I m p o r t c l a s s w h i c h draws t h e w i d g e t s

from e l e m e n t p r o p u i import E l e m e n t p r o p . . . # I n i t i s a u t o m a t i c a l l y c a l l e d when t h e window i s created def init ( s e l f , root , p r o j e k t ) : Elementprop . init ( self , root ) s e l f . r o o t=r o o t s e l f . r o o t . t i t l e ( E le men t p r o p e r t i e s ) s e l f . p r o j e c t=p r o j e c t s e l f . loadlistbox () ; s e l f . entnrelement . i n s e r t (0 , s t r ( projekt . getprobleminfo () [ 0 ] ) )

. . . #

F u n c t i n s w hi c h i s c a l l e d when t h e c l o s e b u t t o n i s p r e s e t i n t h e sub window

def btnClose command ( s e l f , a r g s ) : s e l f . root . destroy () pass

A start le is needed to change some preference as the title of the main window and the extra initialize function, which is described above is needed too in the mainframes source code. This is also specic for Komodo. The start le is included in appendix A.1. To quit an application from a menu created in Komodo use root.quit if root is the name of the instance of Tkinter. The input data windows contains listboxes, entries, labels, checkbuttons, frames and buttons. All these widgets are easy to control with help form the documentation except the checkbutton. Checkbuttons are controlled with built in variables in Tkinter. These variables are created with the variables that are assigned to be a Tkinter class. If this main variables is root then the command root.setvar(name,value) creates a variable. To read the stored value of this variable the command getvar is used instead. This variable is always a string. Other types of built in variables can be used, but then the name of the variables are set automatically. This is an disadvantage in combination with Komodo GUI builder since the name of variables to control widgets are set manually. The good thing with these variables is 39

that the variable change automatically when e.g a checkbutton is ticked. The on and o value of a checkbutton can be set to any values, the default is 1 for on and 0 for o in Komodo. To make a listbox in Komodo GUI builder hold a selection when other widgets are selected the preference export selection must be NO. General for all widgets are that if they are disabled it is the same as if they are read-only. The import module tkMessageBox is used to show short messages in new windows with an OK button. A function that can be a bit hard to handle is the binding command for events e.g a mouse click or the enter button is pressed. More instructions on how to use a binding event can be found on Pythonwares homepage [17]. Python is started with a console but by giving a Python le the extension PYW it is run without a console.

4.1.6

Python to executable le

Running a Python application on Linux is easy as Python is built in to Linux. A Python application can only be run on Windows if Python is installed or Python scripts are converted into a standalone binary Windows application using a special tool. This tool is called Py2exe [18] and can be found on the Internet. Py2exe makes it possible to run Python program on any Windows computer with or without having Python installed. It is very easy to use, only a small setup le has to be written. To convert 2D Truss into a executable le the following setup le can be used.
# s e t u p f i l e f o r 2 DTruss

from d i s t u t i l s . c o r e import s e t u p import p y 2 e x e s e t u p ( windows =[ s t a r t . pyw ] ) # S t a r t . pyw i s t h e f i l e t h a t i s r u n t o s t a r t 2 DTruss

Some additional les can be necessary if the Fortran compiler uses a separate run-time library.

4.2

Graphical user interface for F2PY

F2PY is normally controlled from the command prompt in windows as mentioned in section 3.4.1. Students following the Software Development for Technical Systems course are often non-programmers, which often also means that they are not used to the command prompt. Therefore a graphical 40

interface has been implemented for F2PY, which makes it easier to use and more eort can be put into learning Fortran and Python instead. The F2PY user interface is made in Python with ActiveState Komodo 3.0 GUI builder, illustrated in gure 4.12. The user interface consist of a single window that makes it easy to understand and use.

Figure 4.12: Graphical F2PY The user interface for F2PY has multiple support for Fortran les so Fortran code can be divided into multiple Fortran les were the main module has to be specied. The main module must always be selected in the program. An unlimited number of submodules can be added and this is optional requirement. The only additional settings that is needed is the name of the Python module, the directory of the module that is built and if a log le shall be created. The log le is saved in a text le in the same directory as the generated Python module. If any errors occurs during the compilation the text le is displayed in any cases and the errors are highlighted. This makes the user interface very simple to use as only one Fortran le needs to be selected and then the program can create a Python module. A Python module is created with F2PY when the create Python module button is pressed. The application creates a text string with the modules and settings to F2PY. A runtime operation with the text string is done in Windows command prompt that executes F2PY with the generated string.
# Open commando promt t o r u n t h e commandline generated e a r l y e r r , w=o s . popen4 ( command ) Command i s a s t r i n g w hich i s g e n e r a t e d w i t h t h e

41

same commands a s a r e u s e d t o r u n F2PY i n t h e command promt # Runs t h e commandoline and r e a d s t h e o u t p u t

t e x t=w . r e a d l i n e s ( )

Disadvantage with the wizard is that not all setting for F2PY are supported, but normally it shall work without any problems if it is possible to write attributes for variables in the Fortran code. F2PY user interface is so far in its early stages as not all functions of the F2PY tool is reected in the user interface, but they will be added when the need advises.

42

Chapter 5

Summary and Conclusions


5.1 Summary

This master thesis has investigated how forthcoming courses in Software Development for Technical Systems can be implemented with focus on Fortran integration in a script environment such as Python. A nite element application is created where Python is used for the graphical parts and Fortran for computational parts. A tool F2PY was used to create an interface between Python and Fortran. The focus was on the implementation of the linking with F2PY. The application should also have the possibility to be created by non-experienced programmers. They shall focus on Python and Fortran and not learning the intricate details of a complicated language or interface. Python is also examined to see if it fullls the requirement a nite element application has on the user interface. Finally the application shall be platform independent.

5.2

Conclusions

F2PY is capable of creating Python modules in a single step from Fortran source code and if Numeric F-contiguous variables are used, not a single line of code have to be added to the Fortran code. This makes Python most suitable to create an interface as it is easy to use. Using the created modules in Python is also easy as the same calling conventions as calling internally are used. F2PY is a exible tool as all major features in Fortran are supported, and the advantages of Fortran are conserved. The disadvantages with F2PY are that it requires ve prerequisite and that matrices are stored dierently in Python and Fortran. Overall F2PY is surprisingly good tool to create an interface between Python and Fortran and it fullls all requirements when used in Microsoft Windows. Python code is easy to implement and has an easy structure since Python is an advanced script language. The easy code structure render possibility 43

to rapid development and makes Python applications easy in development. User interfaces are developed with the toolkit Tkinter in a GUI-builder. This also decreases developing time and Tkinter contains all necessary widgets and functions for development of user interfaces. Most operations in Python requires a small amount of code if built-in functions are used. Creating complex and exible applications are also possible as Python support object oriented programming and have a good capability to glue other components. Disadvantages with Python are that everything can be done in many dierent ways so it can be confusing. Extension toolkits can be need for Tkinter if more advanced user interfaces are wanted. Replacing Delphi with Python encourage new possibilities in the developing of nite element application. The possibilities can be updating software, adding plug-ins, create user interfaces rapid for applications and easy development. The combination with Python, Fortran and F2PY can be used on most operating systems since all parts are platform independent. F2PY modules has to be compiled for each platform but the same Python source code can be run on any platform. This results in, the next time Software Development for Technical Systems is given a change in programming languages to Python instead of Borland Delphi is recommended. Fortran is still recommended to be used as the computational language since a link between Python and Fortran is possible to perform. To perform the interface the tool F2PY is suggested to be used. Python has good possibilities to create a user interface if it is used with a GUI-builder.

5.3

Future Work

Some suggestions for future work in this area: Investigate if it is possible to create a nite element toolbox for Python, which consists of functions and modules implemented in Fortran. Study the gluing possibilities for Python, as gluing a complex mesh generator and solver to a Python user interface.

44

Bibliography
[1] Henning, Michi & Vinoski, Steve Advance CORBA Programming with C++, Addison Wesley Longman, USA, 1999 [2] Lindemann, Jonas Programming and visualisation techniques in nite element software, Licentiate Dissertation, KFS i Lund AB, Lund, Sweden, 2001 [3] Lindemann, Jonas & Dahlblom, Ola Till ampad Programmering, 5:e utg avan, KFS i Lund AB, Lund, Sweden, 2003 [4] Lutz, Mark, Programming Python second edition, Oreilly, USA, 2001 [5] Lutz, Mark & Ascher, David, Learning Python, Oreilly, USA, 1999 [6] Ousterhout, John K., Scripting: Higher Level Programming for the 21st Century, http://home.pacbell.net/ouster, 2004-12-02, The article appeard in IEEE Computer magazine March 1998 Internet references [7] Activestate Komodo 3.1 homepage, www.activestate.com, 2005-02-13 [8] Arnholm, Carsten Mixed language programming using C++ and FORTRAN 77, Version 1.1, 28-May-1997, home.online.no/arnholm [9] BrainyEncyclopedia, Library (computer science), http://www.brainyencyclopedia.com/encyclopedia/l/li/library computer science .html, 2005-02-16 [10] Mathworks, MATLAB, http://www.mathworks.se, 2005-02-16 [11] Numerical Python, Numeric and Numarray, http://numeric.scipy.org/, 2005-02-24 45

[12] Object Management Group CORBA homsite, http://www.corba.org, 2005-02-10 [13] Peterson, Pearu F2PY User Guide and Reference Manual, Revision 1.25, 2005-01-30, http://cens.ioc.ee/projects/f2py2e/usersguide/f2py usersguide.pdf [14] Python.org Documentation, http://www.python.org/doc, 2005-02-18 [15] Python.org, GUI programming in Python, http://www.python.org/moin/GuiProgramming, 2005-02-10 [16] Python.org, wxPython, http://www.python.org/moin/wxpython, 2005-02-10 [17] Pythonware Chapter 7. Events and Bindings, http://www.pythonware.com/library/tkinter/introduction/eventsand-bindings.htm, 2005-02-18 [18] Python to Executable homepage http://starship.python.net/crew/theller/py2exe/, 2005-02-10 [19] Secret Labs PythonWare and ebot.org, www.Pythonware.com & www.ebot.org, 2004-12-02 [20] Simplified wrapper and Interface Generator homepage, http://www.swig.org, 2005-02-10 [21] Structural Mechanics, Lunds Institue of Technology, http://www.byggmek.lth.se, 2005-02-10 [22] Tecfacs, Overview of Dynamic Linking, http://www.tecfacs.com/dynamic.htm, 2005-02-16 [23] wxPythons official homepage http://www.wxpython.org/, 2005-02-13

46

Appendix A

Python Modules
A.1
# #

Start
S t a r t f i l e f o r 2 DTruss I m p o r t modul w i t h t h e m a inf ra m e f o r 2 DTruss

from MainFrame import # Make a l o o p

try : u s e r i n i t () except NameError : pass r o o t = Tk ( ) demo = CustomMainFrame ( r o o t ) r o o t . t i t l e ( 2 DTruss ) # T i t l e o f t h e m a infra m e try : run ( ) except NameError : pass r o o t . p r o t o c o l ( WM DELEimport cpickleTE WINDOW , root . quit ) root . mainloop ()

A.2

Mainframe
MainFrame . py UI g e n e r a t e d by GUI B u i l d e r B u i l d 107673 on 2005 02 09 18:18:22 from : W: / 2 DFackverk / MainFrame . u i T h i s f i l e i s auto g e n e r a t e d . Only t h e code w i t h i n # BEGIN USER CODE ( g l o b a l | c l a s s ) # END USER CODE ( g l o b a l | c l a s s )

A-1

and code i n s i d e t h e c a l l b a c k s u b r o u t i n e s w i l l be round t r i p p e d . The main f u n c t i o n i s r e s e r v e d . from T k i n t e r import from M a i nF r am e ui import MainFrame # BEGIN USER CODE g l o b a l from b a s e import import modeldraw # END USER CODE g l o b a l c l a s s CustomMainFrame ( MainFrame ) : pass # # # # # BEGIN CALLBACK CODE ONLY EDIT CODE INSIDE THE d e f FUNCTIONS . chkbtnShowEnr command C a l l b a c k t o h a n d l e chkbtnShowEnr w i d g e t o p t i o n command

def chkbtnShowEnr command ( s e l f , a r g s ) : # Check i f t h e c h e c k b u t t o n i s marked o r n o t t h e n t h e e l e m e n t n u m b e r s a r e drawn o r deleted

i f i n t ( s e l f . r o o t . g e t v a r ( showElNr ) ) : modeldraw . p r i n t E l e m e n t N r ( s e l f . canmain , projekt ) else : s e l f . canmain . d e l e t e ( e l n r ) pass # # # chkbtnShowNnl command C a l l b a c k t o h a n d l e chkbtnShowNnl w i d g e t o p t i o n command

def chkbtnShowNnl command ( s e l f , a r g s ) : # Check i f t h e c h e c k b u t t o n i s marked o r n o t t h e n t h e n o d e f o r c e s a r e drawn o r deleted

i f i n t ( s e l f . r o o t . g e t v a r ( showNodeForce ) ) :

A-2

modeldraw . p r i n t N o d e F o r c e ( s e l f . canmain , projekt ) else : s e l f . canmain . d e l e t e ( n o d e f o r c e ) pass # # # chkbtnShowNnr command C a l l b a c k t o h a n d l e chkbtnShowNnr w i d g e t o p t i o n command

def chkbtnShowNnr command ( s e l f , a r g s ) : # Check i f t h e c h e c k b u t t o n i s marked o r n o t t h e n t h e nodenumbers a r e drawn o r deleted

i f i n t ( s e l f . r o o t . g e t v a r ( showNodeNr ) ) : modeldraw . p r i n t N o d e N r ( s e l f . canmain ) else : s e l f . canmain . d e l e t e ( n o d e n r ) pass # # # chkbtnShowNpv command C a l l b a c k t o h a n d l e chkbtnShowNpv w i d g e t o p t i o n command

def chkbtnShowNpv command ( s e l f , a r g s ) : # Check i f t h e c h e c k b u t t o n i s marked o r not then the p r e s c r i b d e s i g n f o r the n o d e s a r e drawn o r d e l e t e d

i f i n t ( s e l f . r o o t . g e t v a r ( showPreNodes ) ) : modeldraw . p r i n t P r e N o d e ( s e l f . canmain , projekt ) else : s e l f . canmain . d e l e t e ( p r e n o d e ) pass # # # def END CALLBACK CODE BEGIN USER CODE c l a s s When t h e f r a m e i s c r e a t e d init ( self , root ) : init ( self , root ) MainFrame .

A-3

s e l f . r o o t=r o o t # Redraw i f t h e window i s m o d i f y l i k e resized . canmain . b i n d ( < C o n f i g u r e > , s e l f . draw ) . r o o t . s e t v a r ( showElNr , 0 ) . r o o t . s e t v a r ( showNodeNr , 0 ) . r o o t . s e t v a r ( showNodeForce , 0 ) . r o o t . s e t v a r ( showPreNodes , 0 )

self self self self self #

Open window f o r s h o w i n g t h e r e s u l t

def f r m S h o w R e s u l t ( s e l f ) : import S h o w R e s u l t window=T o p l e v e l ( ) S h o w R e s u l t . CustomShowResult ( window , p r o j e k t ) window . g r a b s e t ( ) window . f o c u s s e t ( ) window . w a i t w i n d o w ( ) # Open window t h a t shows t h e i n f o r m a t i o n about the problem

def f r m P r o b l e m I n f o ( s e l f ) : import P r o b l e m i n f o r m a t i o n window=T o p l e v e l ( ) Probleminformation . CustomProbleminformation ( window , p r o j e k t ) window . g r a b s e t ( ) window . f o c u s s e t ( ) window . w a i t w i n d o w ( ) p r o j e k t . setCalcMade (0 , s e l f . l b c a l c ) # Open window t o s e t nen and node p r o p e r t i e s

def f r m N o d e I n f o ( s e l f ) : import n o d e i n f o window=T o p l e v e l ( ) n o d e i n f o . CustomNodeinfo ( window , p r o j e k t ) window . g r a b s e t ( ) window . f o c u s s e t ( ) window . w a i t w i n d o w ( ) p r o j e k t . setCalcMade (0 , s e l f . l b c a l c ) # Open a new window t o s e t e l e m e n t p r o p e r t i e s

def f r m E l e m e n t P r o p ( s e l f ) : import e l e m e n t p r o p

A-4

window=T o p l e v e l ( ) e l e m e n t p r o p . CustomElementprop ( window , projekt ) window . g r a b s e t ( ) window . f o c u s s e t ( ) window . w a i t w i n d o w ( ) p r o j e k t . setCalcMade (0 , s e l f . l b c a l c ) # Open window t o s e t p r e s c r i b d e node v a l u e s

def frmPreNodes ( s e l f ) : import p r e s c r i b e d n o d e s window=T o p l e v e l ( ) prescribednodes . CustomPrescribednodes ( window , p r o j e k t ) window . g r a b s e t ( ) window . f o c u s s e t ( ) window . w a i t w i n d o w ( ) p r o j e k t . setCalcMade (0 , s e l f . l b c a l c ) # Open window t o s e t n o d a l f o r c e s

def f r m N o d e F o r c e s ( s e l f ) : import n o d e f o r c e s window=T o p l e v e l ( ) n o d e f o r c e s . C u s t o m N o d e f o r c e s ( window , p r o j e k t ) window . g r a b s e t ( ) window . f o c u s s e t ( ) window . w a i t w i n d o w ( ) p r o j e k t . setCalcMade (0 , s e l f . l b c a l c ) # F u n c t i o n t o open an e x i s t i n g p r o j e c t

def open ( s e l f ) : global projekt p r o j e k t=Open ( ) i n f i l e =p r o j e k t . g e t i n f i l e n a m e ( ) i f i n f i l e : s e l f . root . t i t l e ( i n f i l e ) s e l f . draw ( 1 ,dm=1) p r o j e k t . setCalcMade ( p r o j e k t . isCalcMade ( ) , self . lbcalc ) s e l f . l b s t a t u s . c o n f i g ( t e x t= Normal ) # Function that c a l c u l a t e s the displacment f o r e a c h node and n o r m a l f o r c e s i n e v r e y element

def e x e c u t e ( s e l f ) : Execute ( projekt , s e l f . l b c a l c )

A-5

F u n c t i o n t h a t c r e a t e s a new p r o j e k t

def new ( s e l f ) : global projekt p r o j e k t=Model ( ) New( p r o j e k t ) s e l f . r o o t . t i t l e ( 2D F a c k v e r k New P r o j e c t ) s e l f . draw ( 1 ,dm=1) p r o j e k t . setCalcMade (0 , s e l f . l b c a l c ) s e l f . l b s t a t u s . c o n f i g ( t e x t= Normal ) # Fuction that saves your p r o j e c t

def s a v e ( s e l f ) : i n f i l e =p r o j e k t . g e t i n f i l e n a m e ( ) if infile : Save ( p r o j e k t ) else : s e l f . saveas () # Fuction that save your p r o j e c t as . . .

def s a v e a s ( s e l f ) : SaveAs ( p r o j e k t ) i n f i l e =p r o j e k t . g e t i n f i l e n a m e ( ) i f i n f i l e : s e l f . root . t i t l e ( i n f i l e ) # F u n c t i o n t o draw e l e m e n t s , d i s p a c e m e n t o f the s t r u c t u r e or normalforces in the elements

def draw ( s e l f , e v e n t , dm=None ) : i f dm : modeldraw . D i s p l a y m o d e=dm # get the s i z e of the canvas

h e i g h t= s e l f . canmain . w i n f o h e i g h t ( ) w i d t h= s e l f . canmain . w i n f o w i d t h ( ) # Don t draw a n y t h i n g

i f modeldraw . D i s p l a y m o d e ==1: s e l f . canmain . d e l e t e ( a l l ) # Draw t h e s t r u c t u r e

e l i f modeldraw . D i s p l a y m o d e ==2: s e l f . canmain . d e l e t e ( a l l )

A-6

modeldraw . DrawGeometry ( width , h e i g h t , s e l f . canmain , p r o j e k t , s e l f . r o o t ) # Structure with displacement

e l i f modeldraw . D i s p l a y m o d e ==3: i f p r o j e k t . isCalcMade () : s e l f . canmain . d e l e t e ( a l l ) modeldraw . D r a w D i s p l a c e m e n t ( width , h e i g h t , s e l f . canmain , p r o j e k t , s e l f . root ) else : modeldraw . D i s p l a y m o d e=1 showerror ( Fatal Error , Ber akningar ej utf orda ) # Structuer with normalforces

e l i f modeldraw . D i s p l a y m o d e ==4: i f p r o j e k t . isCalcMade () : s e l f . canmain . d e l e t e ( a l l ) modeldraw . DrawForces ( width , h e i g h t , s e l f . canmain , p r o j e k t , s e l f . r o o t ) else : modeldraw . D i s p l a y m o d e=1 showerror ( Fatal Error , Ber akningar ej utf orda ) # o p t i o n s t o s e t w hic h t o draw

def drawGeo ( s e l f ) : s e l f . draw ( 1 ,dm=2) def d r a w D i s p ( s e l f ) : s e l f . draw ( 1 ,dm=3) def d r a w F o r c e ( s e l f ) : s e l f . draw ( 1 ,dm=4) # Open a r e s u l t f i l e

def o p e n R e s u l t F i l e ( s e l f ) : global projekt p r o j e k t=Model ( ) s e l f . r o o t . t i t l e ( 2D F a c k v e r k R e s u l t a t f i l ) s e l f . draw ( 1 ,dm=1) p r o j e k t . setCalcMade (0 , s e l f . l b c a l c ) s e l f . l b c a l c . c o n f i g ( t e x t= ) s e l f . l b s t a t u s . c o n f i g ( t e x t= E n d a s t resultatfil ) o u t f i l e =t k F i l e D i a l o g . a s k o p e n f i l e n a m e ( t i t l e = en r e s u l t a t f i l , f i l e t y p e s =[( Oppna r e s u l t a t f i l , . l s t ) ,( Alla F i l e r , )

A-7

]) projekt . setoutfilename ( outfile ) s e l f . frmShowResult ( ) # # END USER CODE c l a s s

i s o n ly used i f the frame i s run s e p e r a t l y , i s auto generated .

def main ( ) : # S t a n d a l o n e Code I n i t i a l i z a t i o n # DO NOT EDIT try : u s e r i n i t () except NameError : pass r o o t = Tk ( ) demo = CustomMainFrame ( r o o t ) r o o t . t i t l e ( MainFrame ) try : run ( ) except NameError : pass r o o t . p r o t o c o l ( WM DELETE WINDOW , r o o t . q u i t ) root . mainloop () if name == main : main ( )

A.3
#

Base
B e g i n Module b a s e

i m p o r t o t h e r m o d u le s

import t k F i l e D i a l o g from tkMessageBox import from Numeric import from node import node from e l e m e n t import e l e m e n t import c P i c k l e import s o l v e p r o

B e g i n C l a s s model

c l a s s Model : # Runs when t h e c l a s s i s c r e a t e d

A-8

def

init

( self ):

s e l f . n e l =0 # number o f e l e m e n t s s e l f . nen =0 # number o f n o d e s s e l f . n n l =0 # n u b e r o f n o d a l l o a d e s s e l f . npv =0 # number o f p r e s c r i b e d nodevalues s e l f . n o d e l i s t =[] # l i s t that contains a l l nodes i n the problem s e l f . e l e m e n t l i s t =[] # l i s t that contains a l l elements i n the problem s e l f . i n f i l e = # Name o f t h e i n p u t f i l e s e l f . o u t f i l e = # Name o f t h e o u t p u t f i l e # Array that contains the displacement of the nodes ( a f t e r c a l c u l a t i o n s )

s e l f . d i s p=z e r o s ( s e l f . nen 2 , d ) # Forces in the elements ( a f t e r calculations )

s e l f . e f o r c e s=s o l v e p r o . as column major storage ( zeros ((2 , s e l f . nel ) , d ) ) # calcMade =1 i f c a l c u l a t i o n s a r e made

s e l f . calcMade=0 def s e t p r o b l e m i n f o ( s e l f , n e l=None , nen=None , n n l= None , npv=None ) : i f n e l : s e l f . n e l=n e l i f nen : s e l f . nen=nen i f n n l : s e l f . n n l=n n l i f npv : s e l f . npv=npv def g e t p r o b l e m i n f o ( s e l f ) : r e t u r n [ s e l f . n e l , s e l f . nen , s e l f . n n l , s e l f . npv ] # R e t u r n s t h e node w i t h i n d e x i n t h e n o d e l i s t

def g e t n o d e ( s e l f , i n d e x ) : return s e l f . n o d e l i s t [ index ] # R e t u r n s a e l e m e n t from e l e m e n t l i s t

A-9

def g e t e l e m e n t ( s e l f , i n d e x ) : return s e l f . e l e m e n t l i s t [ index ] # Make a new e l e m e n t

def addElement ( s e l f , e l e m e n t ) : s e l f . e l e m e n t l i s t . append ( e l e m e n t ) # Add a new node t o t h e p r o b l e m

def addNode ( s e l f , node ) : s e l f . n o d e l i s t . append ( node ) node . s e t d o f ( l e n ( s e l f . n o d e l i s t ) 1) # Remove a node

def removeNode ( s e l f , i n d e x ) : del s e l f . n o d e l i s t [ index ] # Remove a e l e m e n t

def r e m o v e E l e m e n t ( s e l f , i n d e x ) : del s e l f . e l e m e n t l i s t [ index ] # Change i n f i l e n a m e

def s e t i n f i l e n a m e ( s e l f , name ) : s e l f . i n f i l e =name # Change o u t f i l e n a m e

def s e t o u t f i l e n a m e ( s e l f , name ) : s e l f . o u t f i l e =name def g e t i n f i l e n a m e ( s e l f ) : return s e l f . i n f i l e def g e t o u t f i l e n a m e ( s e l f ) : return s e l f . o u t f i l e def s e t D i s p A n d E f o r c e T o Z e r o A n d S e t S i z e ( s e l f ) : s e l f . d i s p=z e r o s ( s e l f . nen 2 , d ) # F o r t r a n u s e s column m a j o r s t o r a g e

s e l f . e f o r c e s=s o l v e p r o . as column major storage ( zeros ((2 , s e l f . nel ) , d ) )

A-10

def s e t D i s p A n d E f o r c e ( s e l f , d i s p , e f o r c e s ) : s e l f . d i s p=d i s p s e l f . e f o r c e s=e f o r c e s # r e t u r n s D i s p and e f o r c e s

def g e t D i s p A n d E f o r c e s ( s e l f ) : return [ s e l f . disp , s e l f . e f o r c e s ] # C o n t r o l l s i f a c a l c u l a t i o n i s made

def i s C a l c M a d e ( s e l f ) : r e t u r n s e l f . calcMade def s e t C a l c M a d e ( s e l f , c a l c , l a b e l ) : s e l f . calcMade=c a l c i f c a l c : l a b e l . c o n f i g ( t e x t= Yes ) e l s e : l a b e l . c o n f i g ( t e x t= No ) # # End C l a s s model Model f u n c t i o n s b u t n o t a p a r t o f t h e model class C a l c u l a t e the problem i n f o r t r a n

def E x e c u t e ( p r o j e k t , l b c a l c ) : i n f i l e =p r o j e k t . g e t i n f i l e n a m e ( ) # if Check i f t h e r e i s a i n p u t f i l e infile : p r o j e k t . s e t o u t f i l e n a m e ( i n f i l e [: 3]+ l s t ) # C r e a t e s t h e n e c c e s a r y v a r i a b e l s from t h e model t o c a l c u l a t e t h e p r o b l e m

[ n e l , neq , n n l , npv , eprop , e d o f , f , bc , b , i e r r ]= createArrays ( projekt ) # lg in i f ierrrorr

o u t f i l e =p r o j e k t . g e t o u t f i l e n a m e ( ) p r o j e k t . setDispAndEforceToZeroAndSetSize () d i s p , e f o r c e s=p r o j e k t . g e t D i s p A n d E f o r c e s ( ) # s o l v e p r o u s e s a p y t h o n module c r e a t e d w i t h f 2 p y from f o r t r a n . M a t r i x and

A-11

a r r a y s must be i n numarray o r n u m e r i c f o r m a t t o be a b e l t o u s e s o l v e p r o . c a l c p r o g . e x e c u t e ( n e l , neq , n n l , npv , eprop , e d o f , f , bc , b , e f o r c e s , o u t f i l e , i e r r , disp ) # ierr is a errorflag nonpositive definit i f the probelm i s

i e r r ==1: p r o j e k t . setCalcMade (0 , l b c a l c ) u showerror ( Problemet e j lA st , P r o b l e m e t Adr i n t e p o s i t i v t d e f i n i t u och e j l A st ) l b c a l c . c o n f i g ( t e x t= No ) else : pr o je k t . setDispAndEforce ( disp , e f o r c e s ) p r o j e k t . setCalcMade (1 , l b c a l c ) s h o w i n f o ( K l a r t , Ber Adkningarna Adr utfAu rda ) else : u showerror ( Inte mA j l i g t ! , I n g e n i n d a t a f i l ) # F u n c t i o n t o open a p r o j e k t / i n p u t f i l e

if

def Open ( ) : i n f i l e =t k F i l e D i a l o g . a s k o p e n f i l e n a m e ( t i t l e = Uppna A e t t p r o j e k t , f i l e t y p e s =[( P r o j e k t / i n d a t a , .DAT ) , ( A l l a F i l e r , ) ] ) # projekt . setinfilename ( i n f i l e )

f i l e =open ( i n f i l e , r ) p r o j e k t=c P i c k l e . l o a d ( f i l e ) f i l e . close () return p r o j e k t # C r e a t e s a new p r o j e k t

def New( p r o j e k t ) : projekt . setinfilename ( ) # Saves a p r o j e k t

def Save ( p r o j e k t ) :

A-12

i n f i l e =p r o j e k t . g e t i n f i l e n a m e ( ) f i l e =open ( i n f i l e , w ) c P i c k l e . dump ( p r o j e k t , f i l e ) f i l e . close () # save as

def SaveAs ( p r o j e k t ) : i n f i l e =t k F i l e D i a l o g . a s k s a v e a s f i l e n a m e ( t i t l e = S p a r a e t t p r o j e k t , d e f a u l t e x t e n s i o n= .DAT , f i l e t y p e s =[( P r o j e k t / i n d a t a , .DAT ) , ( A l l a Filer , ) ]) projekt . setinfilename ( i n f i l e ) f i l e =open ( i n f i l e , w ) c P i c k l e . dump ( p r o j e k t , f i l e ) f i l e . close () # Function that c r e a t e s the n e s s e s a r r y a r r a y s t h a t a r e needed to s o l v e the problem with execute

def c r e a t e A r r a y s ( p r o j e k t ) : v a r=p r o j e k t . g e t p r o b l e m i n f o ( ) n e l=v a r [ 0 ] neq=v a r [ 1 ] 2 n n l=v a r [ 2 ] npv=v a r [ 3 ] # Creates the a r r a y s with zeros

i e r r =a r r a y ( 0 ) e p r o p=z e r o s ( ( n e l , 6 ) , d ) e d o f=z e r o s ( ( n e l , 4 ) , l ) f=z e r o s ( neq , d ) b=z e r o s ( neq , l ) bc=z e r o s ( neq , d ) # F i l l the a r r a y s with i n f o r m a t i o n about the p r o b l e m a f t e r a p a t t e r from a i n d a t a manual f o r the f o r t r a n s o l v e r

for i in xrange ( nel ) : e=p r o j e k t . g e t e l e m e n t ( i ) n1=p r o j e k t . g e t n o d e ( e . g e t n o d e s ( ) [ 0 ] 1 ) n2=p r o j e k t . g e t n o d e ( e . g e t n o d e s ( ) [ 1 ] 1 ) e p r o p e l =[ e . g e t p r o p ( ) [ 1 ] , e . g e t p r o p ( ) [ 0 ] , n1 . g e t c o o r d ( ) [ 0 ] , n1 . g e t c o o r d ( ) [ 1 ] , n2 .

A-13

g e t c o o r d ( ) [ 0 ] , n2 . g e t c o o r d ( ) [ 1 ] ] e d o f e l =[ n1 . g e t d o f ( ) [ 0 ] , n1 . g e t d o f ( ) [ 1 ] , n2 . g e t d o f ( ) [ 0 ] , n2 . g e t d o f ( ) [ 1 ] ] e p r o p [ i ]= e p r o p e l e d o f [ i ]= e d o f e l for i in xrange ( var [ 1 ] ) : n=p r o j e k t . g e t n o d e ( i ) f [ i 2]= n . g e t n o d e f o r c e s ( ) [ 0 ] f [ i 2+1]=n . g e t n o d e f o r c e s ( ) [ 1 ] b [ i 2]= n . g e t b ( ) [ 0 ] b [ i 2+1]=n . g e t b ( ) [ 1 ] bc [ i 2]= n . g e t b c ( ) [ 0 ] bc [ i 2+1]=n . g e t b c ( ) [ 1 ] # End f i l l i n g t h e a r r a y s w i t h i n f o r m a t i o n about the problem Transpose the a r r a y s to get the s t o r e d c o l u m n w i s e l i k e f o r t r a n n e e d s and n o t r o w w i s e l i k e p y t h o n makes by d e f a u l t

e p r o p=t r a n s p o s e ( e p r o p ) e d o f=t r a n s p o s e ( e d o f ) r e t u r n n e l , neq , n n l , npv , eprop , e d o f , f , bc , b , i e r r

A.4
# #

Modeldraw
Module modeldraw t o draw i n t h e d r a w i n g a r e a p e r c e n t a g e o f t h e d r a w i n g a r e a t o be drawn

k =0.9 # H a n d e l s what i s g o i n g t o be drawn , 1 = n o t h i n g i s drawn

D i s p l a y m o d e=0 # Coordvalues c a l c u l a t e s the v a r i a b e l s that t r a n s f o r m t h e c o o r d i n a t e s from n o r m a l t o computer c o o r d i n a t e s s y t e m and makes t h e s t r u c u t r e t o f i t i n t o t h e window

def c o o r d v a l u e s ( width , h e i g h t ) :

A-14

g l o b a l s , x0 , y0 s=min ( [ k w i d t h / ( XmaxXmin ) , k h e i g h t / ( YmaxYmin ) ]) x0=s Xmin+(1 k ) /2 w i d t h y0=h e i g h t+s Ymin (1 k ) /2 h e i g h t # C l a c u l a t e s max and min X , Y , i t a l s o r e t u r n s t h e n o d e s X and Y c o o r d i n a t e s i n l i s t s

def maxminXY ( width , h e i g h t , p r o j e k t ) : g l o b a l Xmax , Ymax , Xmin , Ymin , v a r , X , Y v a r=p r o j e k t . g e t p r o b l e m i n f o ( ) X= [ 0 ] v a r [ 1 ] Y= [ 0 ] v a r [ 1 ] for i in xrange ( var [ 1 ] ) : node=p r o j e k t . g e t n o d e ( i ) X [ i ]= node . g e t c o o r d ( ) [ 0 ] Y [ i ]= node . g e t c o o r d ( ) [ 1 ]

i f D i s p l a y m o d e ==2 or D i s p l a y m o d e ==4: Xmax=max (X) Ymax=max (Y) Xmin=min (X) Ymin=min (Y) c o o r d v a l u e s ( width , h e i g h t ) # D i s p l a y m o d e 3 i s d i f f r e n t though t h e max min XY c h a n g e s when t h e d i s p l a c e m e n t i s drawn

e l i f D i s p l a y m o d e ==3: dispX =[0.] var [ 1 ] dispY =[0.] var [ 1 ] d i s p=p r o j e k t . g e t D i s p A n d E f o r c e s ( ) [ 0 ] absdisp =[0.] len ( disp ) f o r i i n x r a n g e ( l e n ( d i s p ) ) : a b s d i s p [ i ]= a b s ( disp [ i ]) sd =0.05 max ( a b s ( max (X)min (X) ) , a b s ( max (Y) min (Y) ) ) /max ( a b s d i s p ) # S c a l e f a c t o r for i in xrange ( var [ 1 ] ) : node=p r o j e k t . g e t n o d e ( i ) d i s p X [ i ]=X [ i ]+ d i s p [ i 2 ] sd d i s p Y [ i ]=Y [ i ]+ d i s p [ i 2+1] sd

A-15

Xmax=max ( max (X) Ymax=max ( max (Y) Xmin=min ( min (X) Ymin=min ( min (Y)

, max ( d i s p X ) ) , max ( d i s p Y ) ) , min ( d i s p X ) ) , min ( d i s p Y ) )

c o o r d v a l u e s ( width , h e i g h t ) r e t u r n dispX , d i s p Y # F u n c t i o n t h a t draws t h e go metry f o r t h e s t r u c t u r e w i t h e l e m e n t n u m b e r s and n o d e s

def DrawGeometry ( width , h e i g h t , canvasMain , p r o j e k t , root ) : i f D i s p l a y m o d e ! = 3 : maxminXY ( width , h e i g h t , projekt ) # Draws one e l e m e n t a t t t h e t i m e

for i in xrange ( var [ 0 ] ) : n o d e s=p r o j e k t . g e t e l e m e n t ( i ) . g e t n o d e s ( ) x1=x0+s X [ n o d e s [ 0 ] 1 ] x2=x0+s X [ n o d e s [ 1 ] 1 ] y1=y0 s Y [ n o d e s [ 0 ] 1 ] y2=y0 s Y [ n o d e s [ 1 ] 1 ] c a n v a s M a i n . c r e a t e l i n e ( x1 , y1 , x2 , y2 , t a g= lines ) c a n v a s M a i n . c r e a t e o v a l ( i n t ( x1 0.03 s ) , i n t ( y1 0.03 s ) , i n t ( x1 +0.03 s ) , i n t ( y1 +0.03 s ) , t a g= c i r c ) c a n v a s M a i n . c r e a t e o v a l ( i n t ( x2 0.03 s ) , i n t ( y2 0.03 s ) , i n t ( x2 +0.03 s ) , i n t ( y2 +0.03 s ) , t a g= c i r c )

canvasMain . t k r a i s e ( t e x t ) # Draws e l e m e n t n u m b e r s i f t h e c h e c k b u t t o n i s filled

i f i n t ( r o o t . g e t v a r ( showElNr ) ) ==1: p r i n t E l e m e n t N r ( canvasMain , p r o j e k t ) # Draws nodenumbers i f t h e c h e c k b u t t o n i s filled

A-16

i f i n t ( r o o t . g e t v a r ( showNodeNr ) ) ==1: printNodeNr ( canvasMain ) # Draws n o d a l f o r c e s i f t h e c h e c k b u t t o n i s filled

i f i n t ( r o o t . g e t v a r ( showNodeForce ) ) ==1: p r i n t N o d e F o r c e ( canvasMain , p r o j e k t ) # Draws p r e s c r i b d e d o f i f t h e c h e c k b u t t o n i s filled

i f i n t ( r o o t . g e t v a r ( showPreNodes ) ) ==1: p r i n t P r e N o d e ( canvasMain , p r o j e k t ) # F u n c t i o n t h a t f i r s t draws t h e g e o m e t r y w i t h DrawGeometry and t h e n ad d s t h e d i s p l a c e m e n t o f the elements in blue c o l o r

def D r a w D i s p l a c e m e n t ( width , h e i g h t , canvasMain , projekt , root ) : dispX , d i s p Y=maxminXY ( width , h e i g h t , p r o j e k t ) DrawGeometry ( width , h e i g h t , canvasMain , p r o j e k t , root ) # Draws one e l e m e n t a t t t h e t i m e for i in xrange ( var [ 0 ] ) : n o d e s=p r o j e k t . g e t e l e m e n t ( i ) . g e t n o d e s ( ) xd1=x0+s d i s p X [ n o d e s [ 0 ] 1 ] xd2=x0+s d i s p X [ n o d e s [ 1 ] 1 ] yd1=y0 s d i s p Y [ n o d e s [ 0 ] 1 ] yd2=y0 s d i s p Y [ n o d e s [ 1 ] 1 ] c a n v a s M a i n . c r e a t e l i n e ( xd1 , yd1 , xd2 , yd2 , f i l l = b l u e , t a g= d l i n e s ) c a n v a s M a i n . c r e a t e o v a l ( i n t ( xd1 0.03 s ) , i n t ( yd1 0.03 s ) , i n t ( xd1 +0.03 s ) , i n t ( yd1 +0.03 s ) , f i l l = b l u e , t a g= d c i r c ) c a n v a s M a i n . c r e a t e o v a l ( i n t ( xd2 0.03 s ) , i n t ( yd2 0.03 s ) , i n t ( xd2 +0.03 s ) , i n t ( yd2 +0.03 s ) , f i l l = b l u e , t a g= d c i r c ) canvasMain . t k r a i s e ( t e x t ) # F u n c t i o n t h a t f i r s t draw t h e g e o m e t r y w i t h DrawGeometry and t h e a dd s a r r o w which a r e e q u i v a l e n t t o t e n s i l e and c o m p r e s s i v e normalstress

A-17

def DrawFo rces ( width , h e i g h t , canvasMain , p r o j e k t , r o o t ): from math import s q r t DrawGeometry ( width , h e i g h t , canvasMain , p r o j e k t , root ) f o r c e=p r o j e k t . g e t D i s p A n d E f o r c e s ( ) [ 1 ] f o r c e=f o r c e [ 0 ] absforce =[0.] len ( force ) f o r i i n x r a n g e ( l e n ( f o r c e ) ) : a b s f o r c e [ i ]= a b s ( force [ i ]) s d =0.1 max ( a b s ( XmaxXmin ) , a b s ( YmaxYmin ) ) /max ( a b s f o r c e ) #S k a l f a k t o r # Draws one e l e m e n t a t t t h e t i m e

for i in xrange ( var [ 0 ] ) : n o d e s=p r o j e k t . g e t e l e m e n t ( i ) . g e t n o d e s ( ) x1=X [ n o d e s [ 0 ] 1 ] y1=Y [ n o d e s [ 0 ] 1 ] x2=X [ n o d e s [ 1 ] 1 ] y2=Y [ n o d e s [ 1 ] 1 ] # Half l e n g t h of the f o r c e arrow h a l f l e n g t h=a b s ( f o r c e [ i ] sd / 2 ) # Calc h a l f the length of the element

l e n g t h t o m i d=s q r t ( ( ( x2 x1 ) / 2 ) 2+(( y1 y2 ) / 2 ) 2) # F i n d s t h e p i x e l were t o s t a r t d r a w i n g the f o r c e arrow

d e l t a x =( l e n g t h t o m i d h a l f l e n g t h ) / l e n g t h t o m i d ( x2 x1 ) /2 d e l t a y =( l e n g t h t o m i d h a l f l e n g t h ) / l e n g t h t o m i d ( y2 y1 ) /2 xd1=x0+s ( x1+d e l t a x ) yd1=y0 s ( y1+d e l t a y ) xd2=x0+s ( x2 d e l t a x ) yd2=y0 s ( y2 d e l t a y ) # If tensile stress

i f f o r c e [ i ] > 0:

A-18

c a n v a s M a i n . c r e a t e l i n e ( xd1 , yd1 , xd2 , yd2 , a r r o w= b o t h , t a g= a r r o w , a r r o w s h a p e =(8 ,10 ,3) , f i l l = blue ) # I f compressive s t r e s s

else : c a n v a s M a i n . c r e a t e l i n e ( xd1 , yd1 , xd2 , yd2 , t a g= a r r o w , f i l l = r e d , a r r o w= b o t h , a r r o w s h a p e =( 8, 10, 5) ) # F u n c t i o n t o draw e l e m e n t number

def p r i n t E l e m e n t N r ( canvasMain , p r o j e k t ) : # Goes t h r o u g h a l l e l e m e n t s and p r i n t s t h e number , v a r [ 0 ] i s number o f e l e m e n t s

for i in xrange ( var [ 0 ] ) : n=p r o j e k t . g e t e l e m e n t ( i ) . g e t n o d e s ( ) c a n v a s M a i n . c r e a t e t e x t ( i n t ( ( ( X [ n [0] 1]+X [ n [ 1 ] 1 ] ) s +2 x0 ) / 2 ) , i n t (( (Y [ n [0] 1]+Y [ n [ 1 ] 1 ] ) s +2 y0 ) / 2 ) , t e x t=s t r ( i +1) , f i l l = # AA0000 , t a g= e l n r , a n c h o r= s , f o n t= {MS Sans S e r i f } 12 ) # F u n c t i o n p r i n t node numbers

def p r i n t N o d e N r ( c a n v a s M a i n ) : # Runs a f o r l o o p f o r e a c h node and p r i n t s t h e number , v a r [ 1 ] i s n u b e r o f n o d e s

for i in xrange ( var [ 1 ] ) : c a n v a s M a i n . c r e a t e t e x t ( x0+s X [ i ] , y0 s Y [ i ] , t e x t=s t r ( i +1) , f i l l = b l u e , t a g= n o d e n r , a n c h o r= s , f o n t= {MS Sans S e r i f } 12 ) # F u n c t i o n t h a t draws t h e n o d e f o r c e s

def p r i n t N o d e F o r c e ( canvasMain , p r o j e k t ) : # F i n d s t h e b i g g e s t n o d e f o r c e and makes i t 10% o f t h e s i z e o f t h e s t r u c t u r e

absf =[] for i in xrange ( var [ 1 ] ) : ftemp=p r o j e k t . g e t n o d e ( i ) . g e t n o d e f o r c e s ( )

A-19

a b s f . append ( max ( a b s ( ftemp [ 0 ] ) , a b s ( ftemp [ 1 ] ) )) s d =0.1 max ( a b s ( XmaxXmin ) , a b s ( YmaxYmin ) ) /max ( a b s f ) #S k a l f a k t o r # Make a l o o p f o r e a c h node and draws an a r r o w t o s y m b o l i z e t h e n o d e f o r c e , one f o r x d i r e c t i o n and one f o r y

for i in xrange ( var [ 1 ] ) : f=p r o j e k t . g e t n o d e ( i ) . g e t n o d e f o r c e s ( ) if f [0]: c a n v a s M a i n . c r e a t e l i n e ( x0+s (X [ i ] f [ 0 ] sd ) , y0 s Y [ i ] , x0+s X [ i ] , y0 s Y [ i ] , a r r o w= l a s t , f i l l = b l u e , t a g= n o d e f o r c e , w i d t h= 2 ) if f [1]: c a n v a s M a i n . c r e a t e l i n e ( x0+s X [ i ] , y0 s ( Y [ i ] f [ 1 ] sd ) , x0+s X [ i ] , y0 s Y [ i ] , a r r o w= l a s t , f i l l = b l u e , t a g= n o d e f o r c e , w i d t h= 2 ) # F u n c t i o n t o draw a s i g n i f t h e node i s p r e s c r i b e d or not

def p r i n t P r e N o d e ( canvasMain , p r o j e k t ) : # Draws t h e s i g n 2% o f t h e s i z e o f t h e structure

s d =0.02 max ( a b s ( XmaxXmin ) , a b s ( YmaxYmin ) ) # Scalefactor # Runs a l o o p f o r e a c h node and c h e c k i f t h e d e e g r e s o f f r e e d o m a t t h e node i p r e s c r i b d e or not .

for i in xrange ( var [ 1 ] ) : b=p r o j e k t . g e t n o d e ( i ) . g e t b ( ) if b[0]: c a n v a s M a i n . c r e a t e l i n e ( x0+s X [ i ] , y0 s ( Y [ i ]+ s d ) , x0+s X [ i ] , y0 s (Y [ i ] sd ) , f i l l = r e d , t a g= p r e n o d e , w i d t h= 2 ) if b[1]: c a n v a s M a i n . c r e a t e l i n e ( x0+s (X [ i ]+ sd ) , y0 s Y [ i ] , x0+s (X [ i ] sd ) , y0 s Y [ i ] , f i l l = r e d , t a g= p r e n o d e , w i d t h= 2 )

A-20

A.5

Elementproperties
e l e m e n t p r o p . py UI g e n e r a t e d by GUI B u i l d e r B u i l d 107673 on 2005 02 08 19:26:20 from : W: / 2 DFackverk / e l e m e n t p r o p . u i T h i s f i l e i s auto g e n e r a t e d . Only t h e code w i t h i n # BEGIN USER CODE ( g l o b a l | c l a s s ) # END USER CODE ( g l o b a l | c l a s s ) and code i n s i d e t h e c a l l b a c k s u b r o u t i n e s w i l l be round t r i p p e d . The main f u n c t i o n i s r e s e r v e d . from T k i n t e r import from e l e m e n t p r o p u i import E l e m e n t p r o p # BEGIN USER CODE g l o b a l

from tkMessageBox import s h o w e r r o r # END USER CODE g l o b a l

c l a s s CustomElementprop ( E l e m e n t p r o p ) : pass # # # # # BEGIN CALLBACK CODE ONLY EDIT CODE INSIDE THE d e f FUNCTIONS . btnClose command Callback to handle btnClose widget option command

def btnClose command ( s e l f , a r g s ) : s e l f . root . destroy () pass # # # btnSave command C a l l b a c k to handle btnSave widget option command

def btnSave command ( s e l f , a r g s ) : try : n1=i n t ( s e l f . e n t f r o m n o d e . g e t ( ) ) n2=i n t ( s e l f . e n t t o n o d e . g e t ( ) )

A-21

emodule=f l o a t ( s e l f . e n t e m o d u l e . g e t ( ) ) a r e a=f l o a t ( s e l f . e n t a r e a . g e t ( ) ) except : s h o w e r r o r ( E r r o r ! , Det v a r i n g a g i l t i g a t a l ) else : i n d e x= s e l f . l b e l e m e n t s . c u r s e l e c t i o n ( ) ; s e l f . projekt . getelement ( in t ( index [ 0 ] ) ) . s e t p r o p ( emodule , a r e a ) s e l f . projekt . getelement ( in t ( index [ 0 ] ) ) . s e t n o d e s ( n1 , n2 ) pass # # # btnuppdate command Callback to handle btnuppdate widget option command

def btnuppdate command ( s e l f , a r g s ) : from e l e m e n t import e l e m e n t temp= s e l f . p r o j e k t . g e t p r o b l e m i n f o ( ) [ 0 ] try : n e l=i n t ( s e l f . e n t n r e l e m e n t . g e t ( ) ) except : s h o w e r r o r ( E r r o r ! , Det v a r i n g e t h e l t a l ) else : s e l f . p r o j e k t . s e t p r o b l e m i n f o ( n e l=n e l ) s e l f . loadlistbox () i f temp<=n e l : f o r i i n x r a n g e ( n e l temp ) : s e l f . p r o j e k t . addElement ( e l e m e n t (0 ,0) ) else : f o r i i n x r a n g e ( temp n e l ) : s e l f . p r o j e k t . r e m o v e E le m e n t ( temp i 1) pass # # # def END CALLBACK CODE BEGIN USER CODE c l a s s I n i t h a pp e n d s when t h e window i s opened init ( s e l f , root , p r o j e k t ) : init ( self , root ) Elementprop . s e l f . r o o t=r o o t s e l f . r o o t . t i t l e ( E lem e nt p r o p e r t i e s )

A-22

s e l f . p r o j e k t=p r o j e k t s e l f . loadlistbox () ; s e l f . entnrelement . i n s e r t (0 , s t r ( projekt . getprobleminfo () [ 0 ] ) ) # F i l l s the l i s b o x with elementsnumbers

def l o a d l i s t b o x ( s e l f ) : s e l f . l b e l e m e n t s . d e l e t e ( 0 , END) n r= s e l f . p r o j e k t . g e t p r o b l e m i n f o ( ) [ 0 ] for i in xrange ( nr ) : s e l f . l b e l e m e n t s . i n s e r t ( i , s t r ( i +1) ) # T h i s b i n d command c o n t r o l s what ha p p e nd s when a e l e m e n t i s e l e c t e d

s e l f . l b e l e m e n t s . b i n d ( < B u t t o n R e l e a s e 1> , self . selectionlbelement ) # When a e l e m e n t i s s e l e c t e d t h e e n t r y s a r e f i l l e d with the a c t u a l l p r o p e r t i e s f o r the e l e m e n t and t h e y can be c hang e

def s e l e c t i o n l b e l e m e n t ( s e l f , e v e n t ) : i n d e x= s e l f . l b e l e m e n t s . c u r s e l e c t i o n ( ) ; e l e m e n t= s e l f . p r o j e k t . g e t e l e m e n t n=e l e m e n t ( i n t ( i n d e x [ 0 ] ) ) . g e t n o d e s ( ) p r o p=e l e m e n t ( i n t ( i n d e x [ 0 ] ) ) . g e t p r o p ( ) s e l f . e n t f r o m n o d e . d e l e t e ( 0 ,END) s e l f . e n t t o n o d e . d e l e t e ( 0 ,END) s e l f . e n t e m o d u l e . d e l e t e ( 0 ,END) s e l f . e n t a r e a . d e l e t e ( 0 ,END) s e l f . entfromnode . i n s e r t (0 , n [ 0 ] ) s e l f . enttonode . i n s e r t (0 , n [ 1 ] ) s e l f . entemodule . i n s e r t (0 , prop [ 0 ] ) s e l f . e n t a r e a . i n s e r t (0 , prop [ 1 ] ) # END USER CODE c l a s s

i s o n ly used i f the frame i s run s e p e r a t l y , i s auto generated .

def main ( ) : # S t a n d a l o n e Code I n i t i a l i z a t i o n # DO NOT EDIT try : u s e r i n i t () except NameError : pass r o o t = Tk ( )

A-23

demo = CustomElementprop ( r o o t ) root . t i t l e ( elementprop ) try : run ( ) except NameError : pass r o o t . p r o t o c o l ( WM DELETE WINDOW , r o o t . q u i t ) root . mainloop () if name == main : main ( )

A.6

Elementproperties ui
e l e m e n t p r o p u i . py UI g e n e r a t e d by GUI B u i l d e r B u i l d 107673 on 2005 02 08 19:26:18 from : W: / 2 DFackverk / e l e m e n t p r o p . u i THIS I S AN AUTOGENERATED FILE AND SHOULD NOT BE EDITED . The a s s o c i a t e d c a l l b a c k f i l e s h o u l d be m o d i f i e d instead . import T k i n t e r c l a s s Elementprop : def init ( self , root ) :

# Widget I n i t i a l i z a t i o n s e l f . labfrm = T k i n t e r . LabelFrame ( root , t e x t = E le m e n t , ) s e l f . frmegenskaper = T k i n t e r . LabelFrame ( root , text = Properties , ) s e l f . lbelements = Tkinter . Listbox ( s e l f . labfrm , a c t i v e s t y l e = dotbox , exportselection = 0 , h e i g h t = 15 , takefocus = 1 , width = 0 , ) s e l f . s c r o l l b a r 1 = Tkinter . Scrollbar ( s e l f . labfrm , )

A-24

s e l f . labfnode = Tkinter . Label ( s e l f . frmegenskaper , t e x t = From node , ) s e l f . labtnode = Tkinter . Label ( s e l f . frmegenskaper , t e x t = To node , ) s e l f . labe = Tkinter . Label ( s e l f . frmegenskaper , t e x t = E ( Pa ) , ) s e l f . laba = Tkinter . Label ( s e l f . frmegenskaper , t e x t = Area (m2) , ) s e l f . entfromnode = Tkinter . Entry ( s e l f . frmegenskaper , takefocus = 1 , w i d t h = 10 , ) s e l f . enttonode = Tkinter . Entry ( s e l f . frmegenskaper , takefocus = 1 , w i d t h = 10 , ) s e l f . entarea = Tkinter . Entry ( s e l f . frmegenskaper , w i d t h = 10 , ) s e l f . entnrelement = Tkinter . Entry ( root , width = 5 , ) s e l f . l a b n r e l = Tkinter . Label ( root , t e x t = Number o f e l e m e n t s , ) s e l f . b t n u p p d a t e = T k i n t e r . Button ( r o o t , t e x t = Update , ) s e l f . b t n S a v e = T k i n t e r . Button ( s e l f . frmegenskaper , t e x t = Save , ) s e l f . b t n C l o s e = T k i n t e r . Button ( r o o t , text = Close , ) s e l f . entemodule = Tkinter . Entry ( s e l f . frmegenskaper , w i d t h = 10 ,

A-25

) # w i d g e t commands s e l f . lbelements . configure ( xscrollcommand = s e l f . lbelements xscrollcommand ) s e l f . lbelements . configure ( yscrollcommand = s e l f . s c r o l l b a r 1 . s e t ) sel f . scrollbar 1 . configure ( command = s e l f . l b e l e m e n t s . y v i e w ) s e l f . entfromnode . c o n f i g u r e ( invalidcommand = s e l f . entfromnode invalidcommand ) s e l f . entfromnode . c o n f i g u r e ( validatecommand = s e l f . entfromnode validatecommand ) s e l f . entfromnode . c o n f i g u r e ( xscrollcommand = s e l f . entfromnode xscrollcommand ) s e l f . enttonode . co nfigure ( invalidcommand = s e l f . enttonode invalidcommand ) s e l f . enttonode . co nfigure ( validatecommand = s e l f . enttonode validatecommand ) s e l f . enttonode . co nfigure ( xscrollcommand = s e l f . enttonode xscrollcommand ) s e l f . entarea . configure ( invalidcommand = s e l f . entarea invalidcommand ) s e l f . entarea . configure ( validatecommand = s e l f . entarea validatecommand ) s e l f . entarea . configure ( xscrollcommand = s e l f . entarea xscrollcommand

A-26

) s e l f . entnrelement . configure ( invalidcommand = s e l f . entnrelement invalidcommand ) s e l f . entnrelement . configure ( validatecommand = s e l f . entnrelement validatecommand ) s e l f . entnrelement . configure ( xscrollcommand = s e l f . entnrelement xscrollcommand ) s e l f . btnuppdate . c o n f i g u r e ( command = s e l f . btnuppdate command ) s e l f . btnSave . c o n f i g u r e ( command = s e l f . btnSave command ) s e l f . btnClose . configure ( command = s e l f . btnClose command ) s e l f . entemodule . c o n f i g u r e ( invalidcommand = s e l f . entemodule invalidcommand ) s e l f . entemodule . c o n f i g u r e ( validatecommand = s e l f . entemodule validatecommand ) s e l f . entemodule . c o n f i g u r e ( xscrollcommand = s e l f . entemodule xscrollcommand )

# Geometry Management s e l f . labfrm . grid ( in = root , column = 1 , row = 1, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 4 , s t i c k y = news )

A-27

s e l f . frmegenskaper . grid ( = root , in column = 2 , row = 1, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 4 , s t i c k y = news ) s e l f . lbelements . grid ( in = s e l f . labfrm , column = 1 , row = 1, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , s t i c k y = news ) self . scrollbar 1 . grid ( in = s e l f . labfrm , column = 2 , row = 1, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , s t i c k y = nsw ) s e l f . labfnode . grid ( in = s e l f . frmegenskaper , column = 1 , row = 1, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = ) s e l f . labtnode . grid (

A-28

in = s e l f . frmegenskaper , column = 1 , row = 2, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = ) s e l f . labe . grid ( in = s e l f . frmegenskaper column = 1 , row = 3, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = ) s e l f . laba . grid ( in = s e l f . frmegenskaper column = 1 , row = 4, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = ) s e l f . entfromnode . g r i d ( in = s e l f . frmegenskaper column = 2 , row = 1, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = ) s e l f . enttonode . g r i d ( = s e l f . frmegenskaper in

A-29

column = 2 , row = 2, co lumnsp an = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = ) s e l f . entarea . grid ( in = s e l f . frmegenskaper , column = 2 , row = 4, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = ) s e l f . entnrelement . grid ( in = root , column = 4 , row = 1, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , s t i c k y = w ) self . labnrel . grid ( in = root , column = 3 , row = 1, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = e ) s e l f . btnuppdate . g r i d ( = root , in column = 4 ,

A-30

row = 2, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , s t i c k y = w ) s e l f . btnSave . g r i d ( in = s e l f . frmegenskaper , column = 2 , row = 5, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = ) s e l f . btnClose . grid ( in = root , column = 4 , row = 4, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = ) s e l f . entemodule . g r i d ( in = s e l f . frmegenskaper , column = 2 , row = 3, co lumnspan = 1 , ipadx = 0 , ipady = 0 , padx = 0 , pady = 0 , rowspan = 1 , sticky = )

# Resize Behavior

A-31

root . g r i d r o w c o n f i g u r e (1 , weight = 0 , m i n s i z e = 3 5 , pad = 0 ) root . g r i d r o w c o n f i g u r e (2 , weight = 0 , m i n s i z e = 4 0 , pad = 0 ) root . g r i d r o w c o n f i g u r e (3 , weight = 0 , m i n s i z e = 6 4 , pad = 0 ) root . g r i d r o w c o n f i g u r e (4 , weight = 0 , m i n s i z e = 2 7 , pad = 0 ) root . grid columnconfigure (1 , weight = 0 , m i n s i z e = 1 2 7 , pad = 0 ) root . grid columnconfigure (2 , weight = 0 , m i n s i z e = 1 3 3 , pad = 0 ) root . grid columnconfigure (3 , weight = 0 , m i n s i z e = 1 0 2 , pad = 0 ) root . grid columnconfigure (4 , weight = 0 , m i n s i z e = 5 1 , pad = 0 ) s e l f . labfrm . g r i d r o w c o n f i g u r e (1 , weight = 0 , m i n s i z e = 2 1 7 , pad = 0 ) s e l f . labfrm . grid columnconfigure (1 , weight = 0 , m i n s i z e = 1 0 2 , pad = 0 ) s e l f . labfrm . grid columnconfigure (2 , weight = 0 , m i n s i z e = 2 , pad = 0 ) s e l f . frmegenskaper . grid rowconfigure (1 , w e i g h t = 0 , m i n s i z e = 4 0 , pad = 0 ) s e l f . frmegenskaper . grid rowconfigure (2 , w e i g h t = 0 , m i n s i z e = 4 0 , pad = 0 ) s e l f . frmegenskaper . grid rowconfigure (3 , w e i g h t = 0 , m i n s i z e = 4 0 , pad = 0 ) s e l f . frmegenskaper . grid rowconfigure (4 , w e i g h t = 0 , m i n s i z e = 3 1 , pad = 0 ) s e l f . frmegenskaper . grid rowconfigure (5 , w e i g h t = 0 , m i n s i z e = 4 0 , pad = 0 ) s e l f . frmegenskaper . grid columnconfigure (1 , w e i g h t = 0 , m i n s i z e = 4 0 , pad = 0 ) s e l f . frmegenskaper . grid columnconfigure (2 , w e i g h t = 0 , m i n s i z e = 4 0 , pad = 0 )

A-32

Appendix B

Fortran Modules
B.1 Calcprog
! F i l e calcprog . f90 module c a l c p r o g ! I m p o r t i n g sub m o d u l e s use b a r e l e m e n t use s o l v e use o u t p u t f i l e contains s u b r o u t i n e e x e c u t e ( n e l , neq , n n l , npv , eprop , e d o f , f , bc , b , eforces , outfile , ierr , displace ) ! D e c l a r a t i o n o f e x p o r t e d v a r i a b l e s . i m p l i c i t none i n t e g e r , parameter : : f p = 8 integer : : nel i n t e g e r : : neq integer : : nnl i n t e g e r : : npv r e a l ( kind =8) : : e p r o p ( 6 , ) integer : : edof (4 ,) r e a l ( kind =8) : : f ( ) r e a l ( kind =8) : : bc ( ) integer : : b () r e a l ( kind =8) : : e f o r c e s ( 2 , )

B-1

character (255) : : o u t f i l e integer : : i e r r (1) r e a l ( kind =8) : : d i s p l a c e ( ) ! Local d e c l a r a t i o n s i n t e g e r : : bandbredd , i , E d o f e l ( 4 ) , n l c s r e a l ( kind =8) : : k e l ( 4 , 4 ) , E p r o p e l ( 6 ) r e a l ( kind =8) , a l l o c a t a b l e : : K m a t r i x ( : , : ) r e a l ( kind =8) : : ftemp ( neq ) ! Open f i l e t o w r i t e r e s u l t t o open ( u n i t =u n i t o u t f i l e , f i l e =o u t f i l e ,& a c c e s s = s e q u e n t i a l , a c t i o n = w r i t e , s t a t u s = unknown ) ! C a l c u l a t e s bandwith b a n d b r e d d=BB( Edof , n e l ) ! Creates s t i f f n e s s matrix a l l o c a t e ( K m a t r i x ( neq , b a n d b r e d d ) ) K m a t r i x =0.0 a p n l c s =1 ! C r e a t e s e l e m e n t m a t r i c e s and a s s e m b l e s t o s t i f f n e s s matrix do i =1, n e l E p r o p e l=Eprop ( : , i ) E d o f e l=Edof ( : , i ) c a l l bar2e ( Epropel , k e l ) c a l l assem ( Kmatrix , k e l , E d o f e l , bandbredd , neq ) end do ! S o l v e s t h e s y s t e m o f l i n e a r e q u a t i o n s w hich g i v e s d i s p l a c e m e n t and r e a c t i o n f o r c e s do i =1, neq d i s p l a c e ( i )=bc ( i ) ftemp ( i )=f ( i ) end do c a l l b a n d s o l v e ( Kmatrix , d i s p l a c e , ftemp , b , neq , bandbredd , n l c s , i e r r ( 1 ) )

B-2

! Computes e l e m e n t f o r c e s ( n o r m a l f o r c e s ) do i =1, n e l E p r o p e l=Eprop ( : , i ) E d o f e l=Edof ( : , i ) c a l l b a r 2 s ( E p r o p e l , E d o f e l , d i s p l a c e , neq , eforces (: , i )) end do ! W r i t e d i s p l a c e m e n t and r e a c t i o n f o r c e s t o f i l e c a l l w r i t e 3 ( ftemp , d i s p l a c e , b , neq ) ! Writes element f o r c e s to f i l e call write4 ( eforces , nel ) close ( u n i t o u t f i l e ) deallocate ( Kmatrix ) return end s u b r o u t i n e e x e c u t e end module c a l c p r o g ! End f i l e c a l c p r o g . f 9 0

B-3

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy