UBC Theses and Dissertations

UBC Theses Logo

UBC Theses and Dissertations

Object-oriented software development in structural engineering 1992

You don't seem to have a PDF reader installed, try download the pdf

Item Metadata


ubc_1992_spring_eldbury_kevin.pdf [ 4.29MB ]
JSON: 1.0050472.json
JSON-LD: 1.0050472+ld.json
RDF/XML (Pretty): 1.0050472.xml
RDF/JSON: 1.0050472+rdf.json
Turtle: 1.0050472+rdf-turtle.txt
N-Triples: 1.0050472+rdf-ntriples.txt

Full Text

OBJECT-ORIENTED SOFTWARE DEVELOPMENT IN STRUCTURAL ENGINEERING by KEVIN MICHAEL ELBURY B.A.Sc. (Civil), The University of British Columbia, 1990 A THESIS SUBMITTED IN PARTIAL FULFILLMENT OF MASTER OF APPLIED SCIENCE in THE FACULTY OF GRADUATE STUDIES Department of Civil Engineering We accept this thesis as conforming to the required standard THE UNIVERSITY OF BRITISH COLUMBIA APRIL, 1992 © Kevin Michael Elbury, 1992 In presenting this thesis in partial fulfilment of the requirements for an advanced degree at the University of British Columbia, I agree that the Library shall make it freely available for reference and study. I further agree that permission for extensive copying of this thesis for scholarly purposes may be granted by the head of my department or by his or her representatives. It is understood that copying or publication of this thesis for financial gain shall not be allowed without my written permission. (Signature) Department of C t v,, Ev6-4 The University of British Columbia Vancouver, Canada Date /2k-p_i. L._ 30^1 44 Z. DE-6 (2/88) Abstract The recent emergence of the object-oriented paradigm has created a very powerful methodology to aid software developers in the creation of complex applications. This technology is quite common in fields such as computer science and computer engineering but still remains relatively unexplored in more traditional disciplines such as Civil Engineering. The paradigm enforces several basic necessities required by complex, modern software applications. These include management of complexity, data modelling, information hiding, software reusability, and software evolution. The purpose of this thesis is to give an overview of the object-oriented paradigm. This discussion includes a review of the necessary requirements of an object-oriented language. This is followed by the presentation of a software diagramming notation which can aid in the data modelling and design of a software system before coding is started. Also presented is a discussion on the pragmatics of object-oriented development. A universal structural analysis preprocessor called "Cross Link" is developed by the author to demonstrate the application of the object paradigm. Cross Link is intended to provide a unified, easy to use, graphical preprocessing environment that can be used as a front end for any type of finite element analysis programme or CADD package. This is achieved through the implementation of a powerful macro programming language which allows users to manipulate the finite element database in many different ways. Table of Contents Abstract^ ii Table of Contents^ iii Table of Figures iv Acknowledgements vii 1 INTRODUCTION^ 1 2 THE SOFTWARE LIFE CYCLE^ 3 2.1 Structured and Object-Oriented Development^ 4 3 BACKGROUND ON OBJECT -ORIENTED (00) SYSTEMS^8 3.1 Framework of an 00 System^ 8 Encapsulation^ 9 Classification 10 Flexible Sharing 12 Interpretation 14 3.2 The Booch 00 Design Notation^ 15 The Process^ 16 Class Diagrams 17 Object Diagrams 19 3.3 Pragmatics of Object-Oriented Development^ 21 Generalization and Specialization^ 21 Designing for Reuse^ 23 4 CROSS LINK: A UNIVERSAL STRUCTURAL ANALYSIS PREPROCESSOR^26 4.1 Requirements^ 27 Overview 27 Preprocessor Requirements^ 29 4.2 Application Framework 30 The Zinc Interface Library 30 4.3 Implementation^ 35 The Structure Framework^ 36 Controllers 38 The Macro Language 40 Interfacing the Macro Language with other Applications^43 4.4 A Sample Session in Cross Link^ 44 Exporting a Structure to the ANSYS Finite Element Programme^53 4.5 Extending Cross Link^ 58 Recognition of the Physical and Finite Element Models^ 58 Extending the Macro Language^ 62 5 CONCLUSIONS^ 64 6 REFERENCES 65 APPENDIX A CROSS LINK MACRO LANGUAGE FUNCTION REFERENCE^67 BIOGRAPHICAL INFORMATION Table of Figures Figure 1. Cross Link as a Universal Structural Analysis Preprocessor^ 2 Figure 2. The Five Phases of the Waterfall Life Cycle^ 3 Figure 3. Top-Down or Structured Software Development 5 Figure 4. The Three Concepts of Object -Oriented Programming^ 6 Figure 5. The Multidimensional View of an Object Oriented System 8 Figure 6. Classification using Classes and Inheritance^ 11 Figure 7. Polymorphism and the Class Hierarchy 13 Figure 8. The Object Design Model for the Booch Notation^ 16 Figure 9. The Class Category Icon^ 18 Figure 10. The Class Icon^ 18 Figure 11. The Class Relationship Icon^ 18 Figure 12. The Class Template^ 19 Figure 13. The Operation Template 19 Figure 14. The Object Icon^ 20 Figure 15. The Object Relationship Icons^ 20 Figure 16. The Object Visibility Symbols 20 Figure 17. The Object Template^ 21 Figure 18. The Object Message Template^ 21 Figure 19. A Class Hierarchy for an Editor Class 22 Figure 20. Revised Editor Class to Enhance Code Reusability^ 23 Figure 21. Reusability Using Subclassing or Construction. 24 Figure 22.^ 28 Sample Objects Supported by the Preprocessor - iv - Figure 23. The Stages of Structural Analysis and Design^ 29 Figure 24. The UI LIST and UI ELEMENT Generic Classes 31 Figure 25. The Zinc Interface Library Class Diagram^ 32 Figure 26. A Partial ZIL Window Object Hierarchy 34 Figure 27. A Standard Window Created by ZIL^ 34 Figure 28. The Cross Link User Interface 35 Figure 29. The Cross Link Application and Utilities^ 36 Figure 30. The Structure Window and Structure Object Framework^ 37 Figure 31. Cross Link Object Diagram^ 37 Figure 32. Cross Link Node Controller Object Diagram^ 38 Figure 33. Layout of the BOB Macro Language Compiler and Interpreter^ 40 Figure 34. Example Tokens Returned Generated by the Lexical Scanner 41 Figure 35. Example Bytecodes produced by the Bytecode Compiler^ 41 Figure 36. Macro to Add Two Numbers^ 42 Figure 37. Resulting Bytecodes from Figure 36 42 Figure 38. Internal Function for the BOB Sin() Library Function^ 44 Figure 39. The Example Frame to be Modelled using Cross Link 45 Figure 40. The Cross Link Editing Environment^ 46 Figure 41. Setting the Structure Limits^ 47 Figure 42. Setting the Structure Display Options^ 48 Figure 43. Placement of the Column Node Points 49 Figure 44. Generation of Nodes and Elements for Top and Bottom Chords^50 Figure 45. Final Placement of Nodes and Elements^ 51 - v - Figure 46. Placing Node Boundary Conditions^ 52 Figure 47. Setting Element Fixity^ 53 Figure 48. Running a BOB Macro 56 Figure 49. Resulting ANSYS Frame Data File^ 57 Figure 50. Example Frame Exported to the ANSYS Programme^ 58 Figure 51. The Physical and Finite Element Structural Models 59 Figure 52. Alternate Implementation of Element Container^ 60 Figure 53. Extending the Assembly Class for Design 61 Acknowledgements I would like to take this opportunity to thank the many people who have helped me in completing this thesis under the Professional Partnership Programme. I extend my gratitude to Mr. Bill Kendrick, P.Eng., Chief Engineer at Canron Inc., and Mr. Dave Halliday, P.Eng., Special Projects Manager at Coast Steel Fabricators Ltd. I also thank Mr. David Lo, P.Eng., for his contribution to this thesis, Mr Manfred Frank, P.Eng., and Mr. Phil Sullivan, P.Eng., for their practical perspectives on the steel fabrication business. Finally, I thank Dr. Siegfried F. Stiemer and Dr. Helmut P. Prion, my graduate advisors, for the valuable support and guidance they provided for me. Kevin M. Elbury 1 INTRODUCTION Software development often involves the process of mapping or decomposing a complex problem space into modules that are ordered and simplified. The success of this mapping is often determined by the methodology used to analyze and design the "building blocks" that will solve the problem. Recent advances in development tools that support the object-oriented paradigm are now giving the software developers the ability to create complex software applications that excel over traditional techniques in modelling a problem space. As engineers, we naturally deal with complexity through the classification and decomposition of concepts into hierarchial or tree-like formations. The object-oriented development process follows in a manner very similar to this so it may be argued that the paradigm is well suited as a development tool for complex engineering applications. Early observations also indicate that object-oriented software is far more economical to produce than software developed using traditional procedural approaches such as Structured Design. This is mostly due to the large amount of code that can be reused both inside and across applications. Object-oriented software also tends to be much more adaptable and easier to maintain as programme requirements change because of features such as encapsulation, inheritance and information hiding. The purpose of this thesis is, firstly, to provide an overview of object-oriented principles in a language independent manner and secondly, to explain the object-oriented development of structural engineering software application. The second chapter of this thesis introduces the software life cycle, a process oriented procedure which most software follows as it is developed. Two different development paradigms are presented: Structured Development and Object-Oriented Development. Different types of knowledge representation are presented and compared with the two paradigms and it is concluded that the structured paradigm follows an algorithmic approach which places the data being modelled secondary to the procedure. Conversely, the object-oriented paradigm follows a more data-centered approach whereby entities are recognized as objects that have both state and behavior. The third chapter outlines the four principles an object-oriented language must support in order to be classified as "object-oriented". These include encapsulation, classification, flexible sharing and interpretation. Also presented is an brief overview of the Booch Design Notation which -1- is a diagramming technique developed to aid designers in the creation of software design specifications. Finally, some practical considerations in object-oriented development are discussed, including classification and designing for reusability.  AutoCAD (DXF) User Defined ANSYSPlane 2.0 Figure 1. Cross Link as a Universal Structural Analysis Preprocessor The fourth and final chapter looks at the design and implementation of Cross Link, a universal structural analysis preprocessor. Developed using object-oriented techniques, the application allows structural analysts to generate finite element models for any type of analysis programme, design utility or CADD (Computer Aided Drafting and Design) application using an easy to use, integrated environment (Figure 1). The preprocessor supports two editing modes. The first, an interactive drawing mode, lets the analyst draw a structure on the display and perform all usual editing operations such as moving, resizing and setting boundary conditions on nodes and elements. The second editing mode, driven by a powerful macro programming language, allows users to write macros to manipulate the structure database in many different ways. For example, macros can be developed to enhance existing editing features, perform automated mesh generation or design parametric structures (ie. a truss with variable span and depth etc.). Most importantly though, the macro facility provides a means for a two way link (import and export) to any type of analysis programme, providing the analysis programme's file format is known. As an example, two macros (for import and export) are developed that bridge Cross Link with the ANSYS finite element programme. -2- Analysis Design Testing 4.166 " Ne./..fedWAVAW., Integration Coding 2 THE SOFTWARE LIFE CYCLE The process model used in software engineering formalizes the phases of the software life cycle to make each more visible. The most general process model is that of the Waterfall Life Cycle, proposed by Royce (1970) (Figure 2). Based on this model, a multitude of specialized paradigms) have evolved that attempt to provide better models of some of the various aspects of the software development process. However, the waterfall life cycle model remains the most widely accepted process model used in software development. The five phases of the cycle include: Analysis, Design, Coding, Testing and Integration. [18] Figure 2. The Five Phases of the Waterfall Life Cycle. Phase 1: Analysis The analysis phase establishes the software system services and constraints through consultation with the users and developers of the system. Generally, the goal is to "build a vocabulary of the problem domain" 2. This involves identification or invention of tangible objects, roles, events, interactions and procedures. The result of this process is a "Software 1 Other paradigms include Exploratory Programming, Prototyping and Formal Transformations [18] 2 Booch, Grady. Object-Oriented Design. pg. 141 [3]. -3- Requirements Document" that must be readable by both users and developers. Popular analysis techniques include Structured Analysis (SA), Object-Oriented Analysis (00A), Domain Analysis and Entity-Relationship Modelling [3,6,18]. Phase 2: Design Using the "Requirements Document", design proceeds with the specification of software components and associated functionalities. The results of design are usually presented in a way that allows for easy transformation into a computer code. Several design techniques exist; correct selection depends on the type of analysis used. The two most common are Structured Design and Object-Oriented Design. Phase 3-5: Coding, Testing and Integration Using the design documents, the problem is coded into the computer using a programming language suitable to the type of analysis and design performed. Testing of each module in the system is then performed according to the specifications in the Requirements Document. This phase is followed by integration whereby all modules and programme units are tested as a whole, again according to Requirements Document specifications. 2.1 Structured and Object -Oriented Development This section introduces the two popular software development paradigms, one established and one emerging. These are the Structured Development and Object-Oriented development paradigms. Of the different software development paradigms that have evolved over the past 30 years, Structured Development (SD) has come forth as an efficient software development technique. Dale and Orshalick describe SD as (Figure 3): 'A design methodology that works from an abstract functional description of a problem (top) to a detailed solution (bottom); a heirarchial approach to problem solving that divides a problem into functional sub-problems represented by modules...The design consisting of a hierarchy of separate modules with lower level modules containing greater detail than higher level modules."3 However, within the past 15 years, progression of the Object-Oriented (00) development paradigm has progressed to the point that it can now be called a formal software development 3 Dale, Nell. and Orshalick, David. Introduction to PASCAL and Structured Design, p. A50 [7]. -4- TOP ABSTRACT  Level 2 "f BOTTOM • PARTICULAR Figure 3. Structured or Top-Down Software Development. technique. Being a formal technique, every phase in the development life cycle fully supports the paradigm. The 00 model views a system as an assembly of objects, each capable of enveloping its own state and behavior. Objects use messages to communicate with other objects. Classes provide a template that describes the behavior of an object and the inheritance mechanism allows a class to be specialized from existing classes (Figure 4). Fundamentally, the 00 paradigm addresses the issues of code reusability, information hiding and software evolution. Structured and Object-Oriented development have evolved essentially from the differing processes humans use to classify knowledge. Loy breaks this classification into two categories: structural representation and functional representation [11]. The structural paradigm organizes knowledge into entities that have both state and services with the services having secondary importance over the state (the Object Oriented paradigm). The functional paradigm, on the other hand, represents knowledge as an algorithm or procedure. Conversely, functional knowledge places the procedure primary and the data secondary (the Structured paradigm). Recognition of these differing representations of knowledge has lead to hybrid analysis and design techniques that bring together the advantages of the structural and functional approaches [8]. - 5 - • - . . • ' - • ' . . ..... • • .. CIRCLE .; -^•^- • CIRCLE :-.(--00 SQUARE - . . . . • • . • • Shape Circle Rectangle Fil ed Circle Filled Rectangle I Object Messages Classes Figure 4. The Three Concepts of Object-Oriented Programming. It is interesting to note the process in which software development occurs using either of the two paradigms. The Structured Development approach is to "divide and conquer". High level or abstract properties of the system are identified and broken down into lower level components. Programme coding then begins with implementation of the low level components, eventually ending in coding at a high level. In this way, analysis and design usually occur top-down and implementation, bottom-up. Thus, any changes made in analysis and design are much more difficult to implement at the coding stage. In object-oriented development, the goal is to identify the major objects or entities in the system. From these, one abstracts as many properties as possible common to all objects. These form the abstract classes which are the foundation of the system. Programme coding then begins with implementation of the abstract classes. The more specialized classes are then implemented using the inheritance mechanism which allows the behavior encapsulated in the parent class(es) to be shared with derived classes. Thus in the object-oriented paradigm, development occurs in the same -6- order in which the classes are abstracted. This makes the process of analysis, design and coding much more synchronized than that of Structured Development. In this way, it becomes much easier to return to any phase in the process life cycle and make modifications as more is learnt about the system. Object Acive Object Classes Prototypes Static Binding Dynamic Binding Static Typing Static Binding :luta . Polymorphism Subciassing Overloading Prototyping 3 BACKGROUND ON OBJECT-ORIENTED (00) SYSTEMS 3.1 Framework of an 00 System The framework of an object-oriented (00) system is built around a multidimensional view of the object paradigm. These dimensions are viewed as the fundamental principles of object orientation that provide the basic building blocks for dealing with complexity in software systems. The principles allow most of the object-oriented developments to date to be classified in a coherent and unified manner, thus allowing for objective evaluation of the many different techniques available. The features found in any given 00 language can be classified into the following principles of object orientation: • Encapsulation • Classification • Flexible Sharing • Interpretation [2] Figure 5. The multidimensional model of an object-oriented system. Within each dimension there exists several different solution techniques. -8- Shown in Figure 5 is the generalized framework (principles) of an 00 system. Each principle lists a series of different techniques that have been used in various languages to apply the principle. Thus, by looking at a particular technique, the framework enables a connection to be made between it and its associated principle. Following is a brief discussion of the principles of 00 systems along with some of the more common associated techniques 4 . Encapsulation Encapsulation (also referred to as information hiding) provides a method of grouping together the various properties5 associated with an identifiable entity in the system into one logical unit (an object). Access to the object is provided via its interface, which defines the protocol users of the object use to communicate (ie. the object's external view). On the other hand, the implementation of an object is the set of properties that only the object itself knows about (ie. the internal view). Snyder describes encapsulation as: "...a technique for minimizing interdependencies among separately written modules by defining strict external interfaces. The external interface of a module serves as the contract between module and clients. If clients depend only on the external interface, the module can be re-implemented without affecting any clients, as long as the implementation supports the same external interface." [17] Object-Oriented languages achieve encapsulation via two techniques: passive objects and active objects. Passive and Active Objects In class based languages, passive objects signify the importance of structural organization of objects. In general, passive objects represent state; this state can only be changed when instructed by other objects. In contrast to class based languages, actor languages are mainly concerned not with the structural organization of objects, but with the "communication structure of interacting 4 It is important to note that most object-oriented languages support any or all of the following principles. This leads to a popular question demanded of many so-called object-oriented languages: Is it really object-oriented? 5 The term property collectively represents the both the state (ie. Member variables) and operations (ie. Member functions) associated with an object. -9- processes"6. This is achieved via active objects. Active objects differ from passive objects in that they encompass their own thread of control. While passive objects can only undergo changes in state when explicitly acted upon, active objects can show behavior without being operated on by another object. Active objects are of direct importance in concurrent or multi-tasking computer systems and will likely become more significant as more computers gain multi-tasking capability. Classification Classification is a higher level approach to encapsulation. Instead of grouping together properties of an entity into an object, classification works to group together objects with common properties. Given that various combinations of classification can be formed in a given system, one must determine exactly how to classify them. Should objects be classified according to particular attributes (ie. Color, shape) or according to the operations performed by objects (ie. Read, write)? Some common methods of classification are discussed below. Classes A class is a template from which objects can be created. It is based on the grouping together of state descriptors and methods for the object. The inheritance mechanism allows one class to acquire, modify or extend the behavior of another class. The result of inheritance is a class hierarchy which is useful for capturing redundant behavior in a particular group of classes (Figure 6). Class relationships are usually expressed using any one of three basic principles: generalization, aggregation or association 7. Generalization denotes the "kind of relationship amongst classes. For example, a highrise is a kind of building. Secondly, aggregation usually denotes the "part of relationship amongst classes. Here, a storey is not considered a kind of building but a part of a highrise. Thirdly, association expresses some type of connotative connection amongst otherwise unrelated classes. As an example, an earthquake may govern the design of a highrise building but in no way can it be considered dependent class of building. 6 Blair, Gordon et. AL, Object Oriented Languages, Systems and Applications, p.62 [2]. 7 Booch, Grady. Object Oriented Design. p.96 [3] - 10 - Rectangle A Circle FilledCircle A I FilledRectangle • Orty1.7 lhgt wid •(x ,v) Point Figure 6. Classification using classes and inheritance. Inheritance allows classes to evolve from simple to advanced. Some consider class based systems to be the most restricted form of classification because construction of a given class hierarchy is sometimes difficult due to the many different (and correct) combinations that may be possible [2]. Despite this, class based systems (ie. C++, Smalltalk, CLOS) are currently most popular in object-oriented computing. Moreover, this style of object orientation solves some of the more pragmatic problems of software development, mainly in the areas of code reusability and program evolution. Prototypes Alongside classes, prototypes provide a second form of classification. A prototype represents the "default behavior for a concept, and new objects can re-use part of the knowledge stored in the prototype by saying how the new object differs from the prototype" [14]. Objects in a prototypical system use the mechanism of delegation to send messages to prototypes that represent general knowledge (in general, any object can serve as a prototype). Similar to class based systems, prototypes also support behavior sharing but in a fundamentally different manner. Objects that share knowledge with a prototype are constructed using an extension object which contains a list of prototypes which can be shared and a personal definition of the object that gives it a unique identity. When an extension object receives a message, it first attempts to respond to the message using its personal part. If this is unsuccessful, it then forwards (delegates) the message to its prototypes. Flexible Sharing 00 systems generally distinguish between two types of techniques, the first being those which support classification and the second being those which support flexible behavior sharing. The techniques discussed in this section enhance behavior sharing and evolution in an 00 system. Polymorphism Polymorphism is one of the most characteristic features of an object-oriented system. It is defined as "the ability of behavior to have an interpretation over more than one class" 8 . Polymorphism represents a shift towards the modelling of common behaviorisms amongst a group of objects. For example, in the class hierarchy shown in Figure 7, every class exhibits a Draw() and Erase() function. Users of any one of these classes can generically send a Draw() or Erase() message to the object and be guaranteed that the it will behave appropriately. If a Draw() message were sent to an instance of class FilledCircle, the Draw() function defined for filled circle may fill the circle and then call the Draw() function for the Circle class to draw the circle's outline. 8 Blair, Gordon. et al. Object Oriented Languages, Systems and Applications, pp. 35,116. [2] - 12 - Point Draw() Erase() Print() Draw() Erase() Circle Draw() Erase() A dRectangle FilledRectangle Draw() Erase() Figure 7. A class hierarchy for the representation of some geometric shapes. Sending the Draw() message to an instance of any of these classes will elicit a uniform response. Subclassing (Inheritance) Subclassing or inheritance incorporates the behavior of one class into another. The new class is called the subclass of the parent or superclass. Through the process of subclassing, a specialization of a class is created that allows existing code to be easily re-used, modified and extended. A subclass may be specialized in several ways: extension, re-definition, or restriction [2]. Using extension a new method is added to the subclass. By using re-definition as a specialization technique, the subclass maintains the same interface as the parent class but some part of the implementation may be re-coded. Restrictive specialization allows the subclass to inherit only a subset of the methods of the parent class. Draw() Erase() Circle Overloading Overloading permits methods in a class hierarchy to use the same name but to overload the meaning. Overloading is actually another form of polymorphism. In the example shown in Figure 7, the Draw() message is an example of an overloaded method (meaning it has a different implementation depending on where it is in the hierarchy). Interpretation The principle of interpretation determines exactly how the techniques of flexible sharing are be implemented, specifically at the point where a program is compiled or interpreted into machine language. The issues of interpretation generally involve the concepts of type checking and binding. When a compiler performs type checking, it determines whether operations are supported by a particular object or type and whether type inconsistencies will result (ie. can a string be added to an integer?). When a compiler performs binding, it tries to locate the correct implementation of a method (which may lie within another superclass). The issue is when to perform typing and binding: compile time (a static process) or run-time (a dynamic process). Binding: Static or Dynamic? As a direct consequence of inheritance, classes no longer contain all information about the class in a central location because of the line of superclasses that may exist before it. Thus, binding ensures that the correct method is attached to an object. Binding may be achieved either statically or dynamically. In static or early binding, methods are bound to objects at compile time. This type of binding relies on the compiler to build a table of class-method relationships and embed calls to methods directly into the code. Static binding has the advantage of no runtime overhead to find the correct method to attach to the object. An additional advantage is that failed bindings (ie. a method that may not exist) are caught at compile time and not at runtime. Conversely, dynamic or late binding allows methods to be attached to objects at run-time. This offers the advantage of increased flexibility but the disadvantage of possible failed bindings (ie. a method does not exist) at runtime. Dynamic binding is a requirement if an object-oriented language is to support polymorphism. - 14 - Typing: Static or Dynamic? In addition to binding, typing determines whether specified operations are supported by an object and whether type inconsistencies will occur as a result. Like binding, this may be done at either compile time or runtime. Static typing offers the advantage of entrapment all type errors before program execution begins. This is because all variables and expressions are explicitly bound to a type at compile time. However, this does impose restrictions on the language. Conversely, dynamic typing ensures correctness of type at runtime. This offers more flexibility for the language but also creates extra runtime overhead and burden for the programmer because error trapping facilities must be provided when type inconsistencies do occur (this would never happen in a staticly typed system). 3.2 The Booch 00 Design Notation Several object-oriented design notations exist today. Most common are the EVB, HOOD (Hierarchial Object-Oriented Design) and OOSD (Object-Oriented Structured Design) notations [2,8]. However, Booch's OOD notation is the most common in North America (HOOD is most common in Europe). The purpose of any design notation is to decompose a complex system into smaller subsystems which are more easily approachable. Additionally, a notation should address the issues of data abstraction, information hiding and responsiveness to change (in the future) [2,3]. This section looks in particular at using the Booch Notation in software design. This design method is attractive because not only is it language independent but can be easily adapted into a CASE (Computer Aided Software Engineering) tool (the notation is to clumsy to use by hand) 9. The Booch notation is based on the Object Model shown in Figure 8 [3]. The Object Model views a software system from several different perspectives. These perspectives include the logical view, the physical view, static semantics and dynamic semantics. The logical view looks at how classes are decomposed and interact with each other while the physical view looks more closely at hardware issues such as where certain classes are defined and implemented and which processes will be 9 The Rose CASE Tool by Rational Systems fully supports the Booch design notation. -15- Dynamic Semantics Static Semantics Logical View Physical View Booch Notation Figure 8. The Object Design Model forms the basis of the Booch Design Notation. performed by what processor (in a concurrent system). In the Booch Notation, class diagrams and object diagrams are used to design and present the physical view of the system. Module diagrams and process diagrams are used to design and present the physical view of the system. The four diagrams listed so far generally describe static processes that are time independent (ie. a snapshot of the system at on instance in time). These are representations of the static semantics of the system. The dynamic semantics of the system describe the time ordering of events (such as message passing). These semantics are designed and presented using state transition diagrams and the timing diagrams. The purpose of this section is to provide a brief overview of some of the diagrams used in the notation - in particular, class diagrams and object diagrams. The complete specification of the Booch Design Notation can be found in reference [3]. The Process The general approach using the Booch Design is a five step method. Blair et. al describe this development using the following steps 10 : (1) identify the objects and their attributes (2) identify the operations required by each object 10 Blair, Gordon et Al., Object-Oriented Languages, Systems and Applications. pp.206-207 [2]. - 16 - (3) establish the visibility of each object relative to other objects (4) establish an interface to each object (5) implement the objects The first step, the identification of objects and their attributes, is probably the most difficult stage in the process because of the multitude of different and correct groupings that may exist in a problem space. Booch suggests identification of key attributes based on the nouns used to describe the problem space. Identification of the operations suffered by and required of each object establishes the static and dynamic semantics of the object. At this stage it is important to look at the operations required of an object because it enforces decoupling of objects from one another. The third step, to establish object visibility, determines the static dependencies required amongst objects. In other words, one determines what objects see and are seen by a given object. The establishment of the interface to an object determines the protocol for which objects can communicate amongst themselves. The interface forms the boundary between the internal and external view (implementation) of an object. The final step involves implementation of the object whereby a representation of each object or class of objects is chosen. Class Diagrams Class diagrams are used to present the class structure (hierarchial information), its specification, and its relationship with other classes. Class diagrams are built using several different icons and templates. These include: • Class Category Icon • Class Icon • Class Relationship Icon • Class Template • Operation Template Class Category Icon Because class diagrams can sometimes get very large, the class category can be used to organize them into meaningful blocks. The class category is used to represent only the highest - 17 - levels of abstraction in the class diagram and thus gives only an overview of the general architecture of the system (Figure 9). Generally, every component in a class category diagram is a high level reference to a class diagram or another class category. name Figure 9. The Class Category Icon. Class Icon The class icon, shown in Figure 10, represents a class in a class diagram. The class name is enclosed within the dashed line. The dashed line is used to show that clients of the class operate on instances of the class (IE. objects) and not the class itself. • class name . • ' - . . . - " • . - Figure 10. The Class Icon. ox^x uses interface 7"------"iolA uses implementation ^ io.^Inherits 0 zero^--),.. instantiates 1 one • zero or more + one or more ? zero or one n n Figure 11. Class Relationship Icons and Cardinality. Class Relationship Icon The class relationship icon shown in Figure 11, displays the various relationships that may exist amongst classes. These include the using, inheritance and instantiation relationships. Using relationships employ a double line with a circle placed by the class that uses the other class. If the circle is filled, the implementation of the class is being used; if not filled, its interface is being used. Circles can be placed on both ends of the icon in instances where there is a two way relationship. -18- Two numbers can be placed on the icon to indicate cardinality, the number of objects affected by the relationship. For example, a container class would have one instance, but many objects in the container so the cardinality here would be 1 to n. If the cardinality is 1 to 1, is is not placed on the icon Inheritance relationships are shown using a single solid line with the arrow always pointing to the parent class (superclass). Class Templates and Operation Template The class template provides the detailed documentation of each class in the system (Figure 12). The information presented is generally an amalgamation of all the other class diagrams. Class templates provide descriptive narrations of the class, inheritance information, class interface and implementation, and descriptions of operations the class perform. Obviously, the class template can become very detailed so it may only be used later on in the analysis/design stage. Additionally, it is not necessary to use all the fields within the template; only the ones capture the important design decisions. The operation template is a spin-off of the class template. The operation template is used to specifically describe the operations (member functions) performed by the class (Figure 13). Name: Documentation: Visibility: Cardinality: Hierarchy: Superclasses: Metaclass: Generic Parameters: Interface/Implementation: Uses: Fields: Operations: Finite State: Concurrency: Space Complexity: Persistence: identifier text exported/private/imported 0/1/n class names class name list of parameters list class names list field list operations state transition diagram sequential/blocking/active text persistent/transitory Name: Documentation: Category: Qualification: Formal Parameters: Result: Preconditions: Action: Postconditions: Exceptions: Concurrency: Time complexity: Space complexity: identifier text text text list of declarations class name object diagram object diagram object diagram list of exceptions sequential /guarded / concurrent/ multiple text text Figure 12.^ Figure 13. The Class Template.^ The Operation Template. Object Diagrams Object diagrams are used to explain objects and their relationships in the logical design of the system. While class diagrams describe the static semantics, object diagrams describe the dynamic semantics of a design. However, the two are closely related since an object is an instance of a class - 19 - and both adhere to the same sets of operations. The difference is "class diagrams document the key abstraction in the system, and object diagrams highlight the important mechanisms to manipulate these abstractions"[3]. An object diagram is completed using the following icons and templates: • Object Icon • Object Relationship Icon • Object Template • Message Template Object Icon and Object Relationship Icon The object icon in Figure 14 is similar to the class icon except a solid line is used to draw the boundary of the object. Figure 14. The Object Icon. list of messages label inside system outside system Figure 15. The Object Relationship Icons. The object relationship icon shows the flow of messages between objects using lines (Figure 15). A solid line represents a relationship amongst two objects inside the system and a grey line provides a method to document the relationship between the object and any objects outside the software application. Figure 16 shows several detailed icons can be placed at the ends of the object relationship icons to express visibility between objects. P parameter shared parameter field F ^shared field Figure 16. The Object Visibility Symbols. Object and Message Templates As with the class template, the object template provides more detailed information about the object, specifically on the class of the object and its persistence qualities (Figure 17). Name:^identifier^ Operation:^operation name Documentation: text Documentation:^text Class:^class name Frequency:^aperiodic / periodic Persistence:^persistent / static / dynamic^Synchronization:^simple / synchronous / balking / timeout /asynchronous Figure 17. Figure 18. The Object Template.^ The Object Message Template. Object message templates document the individual messages an object may send to other objects (Figure 18). This template is generally only used to document time critical operations. 3.3 Pragmatics of Object-Oriented Development Like any other development paradigm, object orientation has its own set of problems, mostly in the area of classification. As already discussed, a large part of the 00 analysis and design process lies in the area of classification - the discovery and invention of key abstractions and their interactions. Most inexperienced designers encounter problems in mapping a complex problem space into something ordered. In class based systems, the class hierarchy is the result of this mapping. However, in most instances, a wide variety of solutions may exist in the creation of a class hierarchy because of many different classification criteria. - 21 - .^• • • • •. •^. •^•^• •^• •^. Field• (abstract) StringField^-. Data validated charact4r •by character • IntegerField • • Data validated characteir by character •DateField •• Data validated character by character • •^' Generalization and Specialization One of the main objectives in building a class hierarchy is to maximize code reusability. This is sometimes done by embedding generic behavior into a base class for use by all derived classes. An example presented by Duntemann [9] shows some of the shortfalls of this philosophy. The example involves implementation of an abstract class called Field which would enable editing of different types of values (a string field, a data field, or an integer field). The Field class takes care of operations that every field requires. This would include painting a title for the field and indicating the field is active but exclude the actual editing of a value. Derived from Field would be the classes that perform the actual editing of the value. Operations in the derived class would include moving the cursor within the field, ensuring that only numbers are only typed into an integer field or deleting characters from the field. The derived classed may include a StringField, anlntegerField or aDateField (Figure 19). It is evident, however, that there is a great deal of code duplication (three times), particularly for processes such as moving the cursor in the field and formatting characters read from the keyboard. Figure 19. A class hierarchy for an editing class to edit strings, integers and dates. Shown in Figure 20, is an alternate proposal for editing different values. This arrangement is built on the the premise that a string class can handle all input and when completed, need only be verified by the child class (DataField or IntegerField). Thus, most of the code used to perform all editing operations is written only once. The problem with this arrangement is that data validation is only performed after the user presses the enter key. A user editing an integer value would be - 22 - . • • • . • • •^. • • • • IntegerField Data validated after carriage return ••• • • • . •^. . DateFleld Data validated after carriage return .^. • • • .^. • • • • • . ' permitted to enter an alphabetic character into the field but would only be informed of the error after pressing the Enter key. In the first arrangement (Figure 19), this scenario would never arise because the code that reads the keyboard is customized to that particular type of field. This highlights a problem that will often be encountered in differient situations. That is, there is a trade-off between code reusability (and therefore programme size) and getting the desired behavior from a class. . • • • - • • • .. • - • - StringField^• • Data validated after^• • carriage return • Figure 20. Revised implementation to enhance code reusability. All editing is performed in StringField and validation is performed by the subclasses. Duntemann refers to this problem as the case of distribution versus extension. In the first scenario, most of the behavior of the class is distributed throughout many subclasses with little embedded in the abstract class. In contrast, the second approach builds a fully functional base class which is then extended to support any required variations. Designing for Reuse Object-oriented programming promises to increase programmer productivity through software reusability through use of the techniques of encapsulation and inheritance. Two different approaches can be used in designing a system to maximize reusability. These are the subclassing approach or the construction approach [20]. In order to compare the two concepts, consider the example of a container class used to hold a list of strings. Assume that a generic container class, Container, holds generic objects that must be derived from the generic class Object. - 23 - . ...•^•^•^• Container ....- • .• . .^...^.. .• • • ...• • • • . Object ...." • . • • • • ...• - • Object . . • • - • • .^• - - ..^.. Container • • -^• - • StringContainer. • .........•StringContainer .• Subclassing Approach Construction Approach  Figure 21. Reusability using the Subclassing Approach or the Construction Approach. The Subclassing Approach The subclassing approach derives StringContainer from Container so that StringContainer, is given complete access to the interface and implementation of Container. Operations for adding or removing objects from Container need not be defined in StringContainer since they are already defined in Container and are be called directly. This is desirable from both reusability and flexibility points of view. On the other hand, subclassing may not be the best alternative in situations where the preceding hierarchy is very large. Here, the large number of methods that are inherited become difficult to manage (since one picks up both interface and implementation). Additionally, information that was cautiously hidden in the implementation part of the class suddenly becomes accessible to a derived class (that maybe should not have that access), thus defeating the whole concept of interface and implementation. The subclassing approach should only be used in instances where the class to be derived is really a subtype of the parent class. The Construction Approach Using the construction approach, the StringContainer is implemented as a derived class of Object. Included in StringContainer is a field which references (uses) the interface to Container. Unlike the subclassing approach, StringContainer now requires methods to be declared to interface with Container (ie. to Add or Remove a string from Container). This approach is beneficial from a maintainability point of view since it only uses the interface to Container and is thus more resilient to any future modifications made in Container. However, many times the interface to the reference class (Container) is insufficient and the designer is forced to use the subclassing approach simply to gain access to a particular method hidden in the implementation part of the class. Additionally, the construction approach requires implementation of additional interface methods to perform operations such as adding and removing strings from the container (if inheritance were used, these methods are automatically included in the derived classes interface). 4 CROSS LINK: A UNIVERSAL STRUCTURAL ANALYSIS PREPROCESSOR In the past, analysts using computer aided structural analysis programmes have had to work at an unnecessarily low level of detail. A typical analysis session would start with a paper sketch of the structure to be analyzed. On this sketch, the analyst would identify all node points and elements. Nodes and elements would be numbered in some particular sequence. From this sketch, the analyst would proceed to enter the data defining the node points and elements into a data file, its format dependent on the analysis programme being used. If the structure being analyzed requires the resources of several different analysis programmes, most times the data would have to be manually re-entered each time. Additionally, since most design offices now use some form of CADD (Computer Aided Drafting and Design), analysis data must be re-entered into the CADD programme for final detailing. Not only is this unproductive, but it also allows for more errors. Throughout the whole analysis procedure, the analyst often expends unnecessary time and energy having to remember correct file formats and maintain correct numbering and connectivity sequences for nodes and elements. Instead of concentrating on the problem at hand, the analyst has to worry about small details that can easily be taken care of by preprocessing software. Clearly, there is a need for structural analysis preprocessing software that allows for intuitive, high level model definition along with a facility that allows the model to be transferred between different analysis and CADD programmes. The Cross Link Universal Structural Analysis Preprocessor, provides a graphical editing environment that allows structural engineers to perform preprocessing without becoming distracted with small details. Using the mouse, the analyst has the capability of draw a structure on the display and then use a host of tools to perform editing operations to manipulate the structure. Cumbersome data file formats or node and element numbering schemes no longer need the attention they have received in the past. Cross Link also addresses the data transfer issue between alternate analysis and CADD programmes ( and is hence called Universal). This been solved via the use of a unique macro programming language. Because the macro language has the capability to manipulate the internal database kept by Cross Link, its uses are limitless: • Automated parametric structure definition, • Mesh generation and refinement, - 26 - • Enhanced editing capabilities such as alignment and transformation, • Design modules and, • Import/Export of data in any format (Binary and ASCII). The purpose of this chapter is to introduce and discuss some of the software design issues in Cross Link with particular emphasis on the data modelling aspects. This will be concluded with a tour through Cross Link including the use of the macro programming language. 4.1 Requirements Overview A software application is required to create and edit a graphical model of a structure which is then used in a numerical analysis programme to analyze deflections and stresses due to loads applied to the structure. Typically, the graphical model is composed of nodes and elements which define key locations and components of the structure. Node points are defined by some spatial coordinates and a code to represent allowable degrees of freedom. Springs may be applied to node points to model semi-rigid support points and can be applied to the same degrees of freedom as the node (x, y and rotational for a 2-D problem). Point loads can also be applied to node points in the same directions as springs. Since springs and loads are not common to every node, they are considered separate entities to the node. Elements are used to model load carrying members in the structure. In the specification of an element, reference is usually made the lower and upper node numbers, a fixity code and the elements geometric properties (ie. cross sectional area, moment of inertia). An element cannot have zero length or be composed of two identical node points. Elements may also contain loads in the form of an offset point load and/or a uniformly distributed load (UDL). The UDL may be specified with either x,y components or as perpendicular to the element. Several other types of elements are often used in analysis. One general type is the plate element, used to model surfaces. These elements are typically composed of a variable number of nodes (typically 3 to 8) defined by a particular numbering sequence. Although it is not required that these elements be supported in this specification, it is expected that the application will later be extended to support them. - 27 - (b) (c) Figure 22. (a) Nodes points with loads and springs. (b) Beam element with UDL and offset point load (c) Some plate elements A session inside the editor would consist of describing the geometry of the structure, assigning preliminary cross sections to the elements, setting node/element boundary conditions and placing springs and loads on the structure. After saving the structure to a file with a format compatible with the analysis being performed, an analysis would be completed to calculate deflections and stresses. The results of the analysis would then be viewed inside a post-processor. At this stage, code requirement checks would be completed to ensure structural components are correctly designed. The user then proceeds back to the preprocessor to make the required changes to the structure and the cycle is repeated again (Figure 23). Resize members Refine mesh Alternate structural system Preprocessing - geometric model - boundary and loading conditions Analysis - calculate displacements - calculate stresses Postprocessing - code check on stresses and deflections Figure 23. The stages of Structural Analysis and Design. Preprocessor Requirements The first objective of the preprocessor is that it be used as tool for taking a structural concept and rapidly developing a design prototype. Hence its power will be in its inherent ability to quickly generate a model and perform basic editing such as moving or re-sizing components, changing boundary conditions or creating loading cases. The second objective is that the preprocessor provide a generic link with other analysis programmes. This link must be user defined to allow complete flexibility in communication between the preprocessor and the desired application. The advantages offered by such a feature are twofold. Firstly, this will allow analysts to do prototyping in a single environment regardless of the type of analysis programme being used. Secondly, the information gap between engineer and draftsperson will likely be bridged due to the preprocessor's ability to import and export data via any CADD drawing interchange standard (ie. DXF or IGES). The first version of the preprocessor should provide support for the following structural components: - 29 - • Nodes with plane translations and rotations • 2-D beam elements with fixity control • Nodal springs and point loads • Element loads - UDL and offset point loads Basic tools should be provided to add, delete, re-size and move components within a user defined coordinate system. 4.2 Application Framework From the requirements presented in the previous section, we may proceed to discuss some of the software implementation details. At this stage, let's look at the application framework for the Cross Link package. The application framework provides a library of highly flexible, pre-written functions to manage the interface between application and user, thus allowing developers to concentrate on problems specific to the application. In this case, a commercial software package called the Zinc Interface Library (ZIL), was selected [21]. This particular library was chosen because it was the first GUI (Graphical User Interface) based library written using object-oriented techniques since the introduction of the Borland C+ + compiler. Additionally, the library is completely portable between DOS and Microsoft Windows. The Zinc Interface Library The purpose of the application framework is to provide an easy to use, customizable user interface to an application. Because ZIL is object-oriented, customization and modification can be achieved quite easily by simply deriving new classes from the existing framework. ZIL has three important classes that form the engine of the library. These are the display manager, the event manager and the window manager. Along with the these, the window class (UIW_WINDOW) and the window object class (UI_WINDOW_OBJECT) are also important in programme development. Before the role of each of these classes is explained, the foundation of the ZIL library must be explained. Generic Classes All of the generic classes in ZIL are built around the concept of the container. A containers is a linked lists which is capable of holding many different types of objects. The only requirement for an object to be registered in a container is that it must be derived from some common class. All containers in ZIL are built from the generic base class, UL LIST and objects to be placed - 30 - in the container must all be derived from the UI ELEMENT base class. In this configuration,_ the container class maintains pointers to the first and last objects in the list and the UL ELEMENT objects provide pointers to the next and previous objects in the list (Figure 24).  UI_LIST UI_ELEMENT's First ^PI FirstObject Next,Previous Last^ I Object^I I Object^I LastObject 1 Figure 24. The UI LIST and UI ELEMENT generic classes._^_ A UI LIST object acts as a manager for a group of objects. Its basic functions include_ insertion and deletion of objects to and from the list. Additionally, the manager can traverse the list and send messages to each object. All classes within ZIL are derived from either the UL LIST class or the UL ELEMENT class (Figure 25). - .^. - •^• . • • .^• • U I_D ISPLAY UI_LIST • . , • • Ul_WINDOW- ' • . . " • • .^. . UI_WINDOVi • . MANAGER . UI DOS TEXT • . bISPLAY • . . • • . • • • •^• UI^ ' OBJECT . . •^. . • • • • . .• UI_ELEMENT • .^• • .^.•^•^•^- •111_11GI GRAPHICS ' • DISPLAY • .^•^• • . . . .UI_MS WINDOWS ' .^DISPLAY^. • • • . . •^• . • • Figure 25. The Zinc Interface Library Class Diagram. The Display Manager The purpose of the display manager (UIDISPLAY) is to encapsulate all display input/output to provide a consistent application to hardware interface that is easily portable to other environments 11 . The first role of the display manager is to provide an interface between the software application and any hardware devices such as printers or video displays. The display manager also acts as a container for all object regions on the display. Whenever an object (ie. a window) is added to the window manager (discussed below), the window manager registers the region with the display manager. The window manager and the display manager then work 11 ZIL is packaged with several display managers that support the following environments: DOS text mode, DOS graphics mode, and Microsoft Windows. By simply changing the display manager the application ports seamlessly to other environments. - 32 - together to determine the areas of all objects in the region list that should be displayed (for features such as overlapped windows). They also determine which objects are affected by events such as mouse clicks. The Event Manager The event manager (ULEVENT_MANAGER) is a container class for all devices (UI DEVICE) attached to the system. UI DEVICE objects (or anything derived from a_^ _ UI DEVICE) usually provide the communication medium between the user and the application_ and are generally responsible for generating events. Example devices include the mouse, the keyboard, a serial port, or a timer. The purpose of the event manager is to poll all of the devices that is holds, looking for events such mouse or keyboard actions. When an event is generated, the event manager informs the window manager of the type of event that occurred. The window manager then tries to determine which object on the display to dispatch the event to. The Window Manager The window manager (UI_WINDOW_MANAGER) is a container class for all window objects. Window objects include windows (UIW_WINDOW) and any objects (discussed below) associated with the window (ie. title bar, borders etc.). The window manager class provides the interface between the event manager and any window objects on the display. In other words, the window manager receives events from the event manager then dispatches them to the appropriate window objects. Windows and Window Objects The UI_ WINDOW_ OBJECT class is an abstract class from which all useable objects such as buttons and icons in ZIL are derived from (Figure 26). In ZIL, window objects are either used to enhance the appearance and behavior of a window or they are used as data fields in a window. This feature is very elegant because it allows the behavior and appearance of the window to be dynamically created and easily customized. Additionally, code size is smaller because only the features that are required are added. Trying to include every window feature provided by ZIL in one data structure or class would not only result in a very inefficient (speed and size) window, but would also be very difficult to maintain. With this dynamic system, each window object is only responsible for itself which results in very easily maintainable objects. - 33 - U1W_INTEGER .. • - • '^' • UIW_REAL • •^' • •^• . ,^• . 1.11W_MAXIMth .^BUTTON , • • •^• . UIW_POP_UP • • ITEM^• ....... . UIW_TITLE •^AWILMINIMIZE . BUTTON^• • • • • • • • • • .UI_WINDOW_• OBJECT •^•^• •^•^' . .USER DEFINED- . OBJECTS • • .^.^. • • , • • . UIW_NUMBER. •., •^. • UIW_ICON^ UIW_BORDER. r Til tUIPtatin.133REIPS.01,131111111,..../Irlar.13£.1.1Rn St.ttirly, X Grid Spacing: 11400 V Grid Spacing: 11400 X Origin: V Origin: 10 10  Display Grid () Vas 0 Points.? No ^1r =MI aanca 1 I Halo I 11111/11,43MMAAM,F,J10. Figure 26. A partial ZIL window object class hierarchy. For example, the window shown in Figure 27 is built from several window objects that allow the window to exhibit a wide variety of behavior. The system button (top left corner), when pressed, opens a menu with options to expand the window to full screen or shrink it to an icon, close it or restore it to its original size. The border object allows the window to be re-sized and the title object not only displays the window title but allows the window to be moved when dragged with the mouse. Figure 27. A standard window created by ZIL. - 34 - The radio buttons (Display Grid Points) show another unique feature of the window class. The radio button class is also a window class (RADIO CONTROL) which can be placed within another window (added to it). The RADIO _CONTROL class corresponds to the area around the two radio buttons (RADIO BUTTON class) and its responsibility is to ensure that when one button is selected that the other is unselected. The RADIO _ BUTTON objects then receive messages from the RADIO_CONTROL to display themselves as selected or unselected. 4.3 Implementation This section briefly describes how the different features of Cross Link have been interfaced with the Zinc Interface Library using the C+ + programming language. It also discusses the implementation of the Cross Link Macro Language that enable users to' modify and customize the operation of Cross Link in many different ways. Detailed internal documentation on Cross Link can be found in reference [10]. Menu Bar Ells Edit &lettings hacro pools &la Structure Window .^• C^\..sil._ I Mt, •,) C:, ME^Ws 1^ Km^T (5600.0 : 4200.0) • Tools 0 ril iii x0 T ,,, • .^.^.^.^. qt.4-4P:-.0-ff::* .:', ...^,...^%,:^\ i /^.:.:^...-*:^/ .. • /1"*.t.:. .^4^. X 1^ .I "^• I Match Nlndow^ 1 i I t^" . ^k Tool Box Watch Window Figure 28. The Cross Link User Interface. - 35 - Analysis Module Postprocessor : Spreadsheet : Application Cross Link Utilities Menu Bar Tool Box Macro Language Structure Database External Utilities Shown in Figure 28 is the Cross Link user interface. It is composed of four windows: the menu bar, the tool box, the watch window and the structure window. These features along with other utilities are also presented in Figure 29. The menu bar provides basic services for Cross Link including options to read and write the database to file, set drawing parameters such as the coordinate system limits, grid points and snap points. The menu bar also contains options to execute user macros, run external applications and obtain help. The tool box contains six icons that let the user select an appropriate editing mode. The watch window is a utility used by the macro language that allows macro programmers to write useful macro results to the display. Most importantly, the structure window, which is the engine of the preprocessor, provides the interface between the user and the database. Figure 29. The Cross Link Application and Utilities The Structure Framework Figure 30 shows the class diagram for the structure framework (using the Booch design notation). The four important classes to recognize in this diagram are the UIW_STRUCTURE class, the STRUCTURE class, the SO_NODE_CONTROL class and the SO ELEMENT CONTROL class. Referring to Figure 28, the UIW_STRUCTURE class corresponds to the structure window and the STRUCTURE class corresponds to the interior border - 36 - . - WI_WINDOW OBJECT. . . - - . • ' ' - - - - , . . . _ - -• . ,^ . , UIW_STRUCTURE .0^(:) STRUCTURE UIW WINDOW 2 • - . , - - . - ' SO_  NODE CONTROL • . .^• - - . • • •• . . . . . ..' . ELEMENT CONTROL' . .^ , - • . . ' - - - - in the structure window. The structure database, which provides storage facilities for nodes and elements, is represented by the two node and element controllers. As already mentioned, the structure window and the structure object provide the interface between all utilities (ie. the menu bar or the macro language) and the structure database. In other words, utilities never communicate directly with the database. ' Ul_WINDOW_MANAGER ' Figure 30. The structure window and structure object framework (using the Booch Notation). In order to demonstrate how the system works, consider the Booch object diagram shown in Figure 31. Shown on the diagram are six objects: a menu bar object (aMenuBar), a tool box object (aToolBox), a structure window object (aStructureWmdow) and two controllers (aElementControl and allodeControl) 12. The two messages displayed on the diagram correspond to a user using the node tool to set the degrees of freedom on some selected nodes (SetDOF) and the using the Edit...Delete menu option to erase some selected nodes (DelectObjects). Following the SetDOF message, it is sent to the aStructureWmdow object who in turn dispatches it to the aStructure object. 12 Container-type objects can be represented in the Booch notation with a series of smaller object icons placed inside the container icon. - 37 - 4SetDOF I DeleteObjects DeleteObjects\ aStructureWindo SetDOF DeleteObjects \DeleteObjects SetDOF aToolBox allodeController The aStructure object then sends the message to the allodeController object which sends the SetDOF message to all selected allode objects. To erase all selected objects, the DeleteObjects message is dispatched in a similar manner except this time, the message is also sent to the aElementController object. Figure 31. Cross Link Object Diagram. Controllers The structure database is represented using the SO_NODE_CONTROL and the SO ELEMENT CONTROL controllers (Figure 32). Controllers provide a powerful, high level method of organizing information. Generally, it is not a requirement of the controller to know the type of objects stored in the container as long as the stored objects abide by the common message protocol defined by the controller. For example, it is perfectly acceptable for a controller to hold a node object and an element object as long as the objects know what type of messages they can receive from the controller. In this implementation however, two controllers were used. Each one was customized specifically for the type of objects that would be contained. UIW WINDOW .^-^- SO GRAPHIC CONTROL^•-^- ' - •IN t I STRUCTURE • • • so_NooLcoNTRol. SO_NODE^ SO_LOAD^• .^- .  SO_SPRING^• .^.^- Ul WINDOW_OBJECT^SO_GRAPHIC .^. Figure 32. Implementation of the SO_NODE_CONTROL class and the SO NODE class. The SO ELEMENT CONTROL and SO ELEMENT classes are similar. Storing the nodes and elements in separate containers was done for efficiency reasons. With structures that consume a large amount of time in displaying themselves, a user has the option to suppress display of a given object (ie. nodes, elements or loads) in order to increase the overall programme efficiency. For example, when the flag is set to suppress the display of nodes, a draw message sent to both controllers is only accepted by the element controller. In a single controller implementation however, there is no way of filtering a message and sending it to a particular group of objects such as elements. This is because the controller now has to iterate through the complete container and for each object, either blindly send the message or determine if it is a candidate for the message. ill BOB Source File The Macro Language The Cross Link Macro Language (BOB) is a powerful object-oriented programming language that can be used by end users of Cross Link [1]. Through a set of callable library functions that access the Cross Link kernel, users can write macros to manipulate Cross Link in many different ways. Appendix A gives and overview of the language and also provides a complete listing of the macro library functions. The macro language is implemented using three modules, the lexical scanner, the bytecode compiler and the bytecode interpreter, which are shown below (Figure 33). token Lexical^—0-^Bytecode Scanner get token ^Compiler r \ Data Dictionary t Stack Bytecode Interpreter sp -to- 4-stk_bottom Figure 33. Layout of the BOB Macro Language Compiler and Interpreter. The Lexical Scanner The purpose of the lexical scanner is to scan a macro file and parse it into tokens which are fed into the bytecode compiler. The lexical scanner does not perform syntax checking but it must distinguish between language keywords and operators (ie. class, if, else, nil, > =, = ) and variables in order to send the correct token to the bytecode compiler (Figure 34). Bytecodes / essassgsasens+ i p 4. 4-stk_top - 40 - T_INTEGER T_FLOAT T_STRING T EO ILE T_IF T AND T_NEW integer value (12) floating point value (1.234) string value ("ab123.0") equal (==) less than or equal to operation (<-.) begin an if statement logical AND (&&) new keyword Figure 34. Some example token values returned by the lexical scanner. The Bytecode Compiler The bytecode compiler calls the lexical scanner to parse the source file and then using its defined syntax rules, converts these tokens into a series of bytecodes 'Which are later interpreted using the bytecode interpreter (Figure 35). The compiler also builds a data dictionary where all variables, functions, class definitions and class implementations are stored. This dictionary is referenced to using the gererated bytecodes. There is a class of possible syntax errors that are not trapped by the compiler and therefore must be located by the interpreter. These errors arise because of the fact that the language is typeless. Being typeless, any variables defined within a macro are not required to be explicitly declared as integers, floats or strings (variable types are set when an assignment is made to the variable - ie. x = 123.1; sets the type of x to a float). Therefore, the compiler cannot check for incorrect operations such as adding an integer to a string because this is unknown at compile time. If the language were typed, type syntax could be checked by the compiler. OP_PUSH OP_ADD OP_DIV OP_GE OP_SET OP CALL push nil onto the stack add the top two stack entries divide the two top stack entries perform "greater than or equal to" on two top entries set the value of a variable call a function Figure 35. Some example bytecodes (or opcodes) produced by the bytecode compiler. The compiler-interpreter arrangement has some advantages over a straight interpreter arrangement (such as BASIC) where syntax checking, compilation and execution are all performed in one pass. Not only is programme execution much faster (because language syntax is verified by the compiler) but development of a runtime-only system that does not include the - 41 - compiler could also be implemented. This would allow a compiled macro to be written to a file where it could later be retrieved and executed using the interpreter (the compiler could be packaged as a separate application). This feature would offer a significant speed advantage in instances where macros are never modified and do not require compilation every time they are executed. The Bytecode Interpreter The bytecode interpreter executes the series of bytecodes that are built by the bytecode compiler to create a running application. It is also responsible for the verification of type correctness at run-time. To show how the bytecode interpreter uses the stack when interpreting bytecodes, consider the macro shown in Figure 36 which adds two numbers together. Shown in Figure 37 are the bytecodes (opcodes) created by the bytecode compiler. main(;i,j,k)^ TSPACE 03 PUSH i = 2.0; LIT ; 2.0 j = 4.0; TSET 02 k = i + j;^ LIT ;4.0 TSET 01 TREF 02 PUSH TREF 01 ADD TSET 00 ; k RETURN Figure 36.^ Figure 37. Macro to add two numbers.^Resulting bytecode instructions execute the function main() in Figure 36. The interpreter uses a stack as a temporary storage facility for intermediate operations and values (Figure 33). The stack pointer (sp) is used to point to different slots on the stack. In the example programme, the TSPACE opcode allocates three temporary slots onto the top of the stack which are used the three local variables i, j and k. A PUSH opcode is then executed to push a slot onto the stack, followed by a LIT opcode which sets the value of the new slot to the value 2.0. Next, a TSET opcode sets the value of the variable i to the current value pointed to by the stack pointer (2.0). The same LIT-TSET sequence is also performed for the assignment to variable j. The TREF opcode then pushes a slot onto the stack and sets the value of this slot to the value of variable i and the same is done for variable j. The ADD opcode is then executed - 42 - which adds the value pointed to by the stack pointer (j) with the value contained in the next slot above the stack pointer. The result is then stored in the slot above the stack pointer and the TSET opcode is issued to set the value of variable k to this value. The RETURN opcode then indicates execution of the function is complete. Interfacing the Macro Language with other Applications The macro language supports two different types of callable functions. The first is any function which is declared in a macro file (ie. a subroutine). The second type of callable function, specified by a developer of the system, is called an internal or library function. As part of the compiler initialization routine, a set of library functions can be added to the data dictionary (a storage dictionary for all macro variables and internal functions) which can then be executed from within a BOB macro. These internal functions are written in C and have to be compiled into the application's executable file. Programming the internal functions requires minimal understanding of the compiler/interprete operation. The external function is written to accept one parameter in the function call, the number of arguments passed in the BOB function. For example, consider the BOB library function Sin (value), which calculates the sine of value. Shown in Figure 38 is the equivalent C function that calculates the sine and returns the result back to the interpreter. Allone need to know in order to add a library function to the language is the state of the stack right before the external function is called. The interpreter will push all the parameters passed to the function onto the stack (in this case only value) so the internal function need only check that the parameters number of parameters were passed and that they are of the correct type (obviously, value can only be of type integer or float). Once the parameter type is verified, it can be extracted from the stack and the calculation can be performed. In order to pass the result back to the interpreter, the stack pointer must be incremented by the number of arguments in the function. After the stack increment, the result will be placed on the stack where the interpreter will insure it is assigned to the correct variable. Using this method, a full complement of functions can be developed to interface BOB with functions and data that are internal to the application. This creates a very high level of flexibility // init functions - initialize the internal functionsvoid init_functions() C // add the BOB Sin() function using a pointer to the sine functionadd_function("Sin",sine); I/ sine calculates the sine of a valuestatic int sine(int argc) C float value, retval; // make sure only 1 parameter was passed by BOB.argcount(argc,1); // ensure the parameter has the correct typeif(!type(O,DT_INTEGER) && !type(O,DT_FLOAT))badtype(0,DT_NUMERIC); // perform the calculationif(type(0,DT_INTEGER))(value^sp(O].v.v_integer;retval = sin(vatue); // call a function to do the calculation else if(type(O,DT_FLOAT))Cvalue = sp(07.v.v_float;retval = sin(value); // increment the stack pointer by the number of params passed (1)sp += argc; // set the value pointed to by sp to the return value of sinset_floataspI0],retval);return(0); Figure 38. The internal function to calculate the sine of the BOB Sin() function. because, with the proper interface to the kernel of the application, it is possible to shift much of the programming from internal development to external development which can be done by end users of the application. 4.4 A Sample Session in Cross Link The purpose of this section is to provide a tour through CLUSAP. In the example, a model of the frame shown in Figure 39 will be developed. Then using the macro language, the frame will be exported to the ANSYS finite element programme for final analysis. Start the Cross Link programme by typingxlink<enter> at the DOS command line. If this is not the first editing session, any structure that was edited in another session will automatically be loaded. A screen similar to that shown in Figure 40 should appear. The preprocessor environment consists of four windows on the display: the Menu Bar, the Tool Window, the Watch Window and the Structure Window. The Menu Bar contains menu options to open and save files, set environment - 44 - 0 LI) O full moment connection req'd full moment connection req'd //.{/f assume full moment transfer betwen web members and chord 14 CP 2000 28 000 Figure 39. The Example Frame to be Modelled using Cross Link. parameters, run macros and obtain help. The Tool Window contains six icons or tools that determine the editing mode. The Structure Window is the window where the structure is displayed and edited. Finally, the Watch Window is used as an output facility for the macro language. Macro developers can use this window display information for users of the macro or use it as a debugging facility (by printing variable values to the window). - 45 - En... Last lettings nacre, Loomis Halo a^ (Untitled)^ 4^1 Teelsi (0.0, 0.0) Zo —0 Node Tool • -^•^- •^Element- Tool^- .^.^.^. .^'^•^'^'Spring' Tobl. . .^.^. .^Point.^Lo.ad . Tool^. • •^•^-^ •^4 .^•^•^UDL • Tool Property Tool .^.^.^-^•^•^ • 11 1111 .,, pi pp 11481 IJ^.^I Watch Windom^ 1 4 I 1. L 1 ,^ ,r Figure 40. The Cross Link Preprocessor Editing Environment. The first step in a session is to set up a coordinate system and a grid sustem. To do this select Settings...Limits from the menu and enter the minimum and maximum coordinates of the frame (allowing for some margin space) in the dialogue box (Figure 41). To set the grid size, select Settings...Grid and enter 500 (mm) for the x and y grid spacings. The Settings...Display option can be used to set some of the structure display options on the screen. In this case, select the display of nodes and node numbers, and element and element numbers (Figure 42). ^r Tools Helm, Iaancst 1 I J^ Watch Window (Untitled) (1000.0 : 6500.0) =I a mc zu a al^mu IN I ^ Mininun x coordinate: 1-2000 Minimum w coordinate: 1-2000 Maximum x coordinate: 128000 Maximum w coordinate: 118000 1 4 1 0 rt File Edit tettinws near° Ioola Uelo Figure 41. Setting the Structure Limits. The preprocessor is now ready to begin definition of the frame. This will proceed with the definition of the node points, then the elements and their properties and finally any boundary conditions (both node and element). To place nodes, select the node tool from the Tools window using the left mouse button. Move over the structure window and click the right mouse button to make it current (the window title bar will highlight). Now, using the left mouse button, add the node points for the two columns (Figure 43). The F9 key can be used to toggle the snap-to-grid option (the coordinate display will tell you if it is on or off). Similarily, F8 will toggle the grid display. If you wish to zoom into a region of the structure to place the nodes, drag the mouse with the right button pressed over the area you wish to zoom. To return to the previous view, click on the Zp ('Zoom Previous') button. - 47 - (Untitled) ToolsI 4' 1 ms(11500.0 : 18000.0) Eile Edit tettings nacro Davis Help Watch Window 4 1 t 0 N Ea A.0 -r ri I aanbel I I Help I — Display Options ED Nodes 11 Node numbers Egi Elements^Element numbersEl Springs Spring stiffnessesLoads Load values 1^ Figure 42. Setting the Structure Display Options. Next, select Edit...Generate to generate a line of nodes for the top and bottom chords (Figure 44). The node generator contains options to control node placement at the beginning and ending coordinates and optional element generation (with or without properties attached). For the bottom chord, start node generation at (0,8500) and end at (28000,8500) using 14 elements. Do not include generation of the first and last nodes because Cross Link will automatically look at these coordinates for a node to connect an element to. 4 I tHatch Window Tools 0 iii (12000.0 : 11000.0) (Untitled) 06 02^ 4 ^ 1^ File Edit lettings nacre Lools help Figure 43. Placement of the Column Node Points. For the top left hand chord, start at (0,10000), stop at (14000,11500) and generate 7 elements. This time, include generation of the last node. For the top right hand chord, start at (14000,11500), stop at (28000,10000) and again generate 7 elements. Do not specify generation of the first and last nodes this time since they already exist. Placement of the remaining web elements can now be performed using the element tool. Select the element tool with the left mouse button, move over the frame and select the first node for an element. A rubber-banded element will follow the mouse cursor until the second node point for the element is selected. Element selection is continuous until you press the <Escape> key. Figure 45 shows the fmal frame model with all nodes and elements placed. Eile Edit lettings Macro tools UelP w^I • (Untitled)^ I iitt Tools (26000.0^ ■^Automatic Nodc Gcmcvatiom^...^1^t  ^Start Point:^End Paint: -^ Zn E)  ^...  ^... ^ .c.,6V., . a1/4\alx = 10^1 X̂ = (28000^Iu . )8500^I^.W = 0500 i  ^Generate n Elements: ...i4; n =^1 14^1 Eli SI ,, AV7 O' .20 0* — Generation Options Generate first node Generate last node Generate elements N Use current  property settings a^Use current fixity settings ^ez..5W x oAL.0 [^ay.^IgAirvmel ^I^Help -   %T., ,,:,,4^- Ilt , rillill • I^ Watch Window^ 1 1 1t1 1 Figure 44. Automatic Generator of Nodes and Elements for Top and Bottom Chords. Now you can place the boundary conditions. Start by selecting the two column support nodes by dragging the mouse with the left button held down. Eight selector icons will appear on the display encompassing the selected objects. The selector icons can perform two operations when the mouse is moved over top of them and then dragged (a different mouse cursor appears when the mouse is over a selector). Dragging a selector icon with the left mouse button down will increase the box size in order to add or remove objects from the selection set. Dragging a selector icon with the right mouse button down will move all selected objects. The F4 key can also be used to add or remove elements from the selection set. The default selection criterion is to select all elements inside and crossing the selector box (the region inside the eight icons). Pressing F4 once will then proceed to select only elements completely inside the selector box. Pressing F4 yet again will proceed to select all elements crossing the selector box. - 50 - Eile Edit lettings ffeero tools Hello , -^• (Untitled)^ 4^t Toole (12500.0 : 6500.0) Zia ED as.25^*RI ... a-i27 '' -^29 --^2s ^ 22 ^4 23^a - ..0^AD^'' '.-^ ''^.1, '''^CD- --  CO ---- - 400 ^31^320?.... 1,p-4e 1 ^(!),,,,^-i--,„ ^.--,-. i^,.-^ „A) ----- -.*^06 Cir..'" - i,s^.•' ,e ll - -4 12^-4.. ;6 2' -, (V ..-- -408^c:4 113^ 0:4 ^6.0 ^®16 ^17 ^40 ^,Isr .  45 ■. 0 1 4 . .ALO-I- in i -..-Z.1^ Watch Window^ 4^t^- Figure 45. Final placement of Nodes and Elements. With the two column support points selected, select the node tool with the right mouse button. A window will appear that will display all possible nodal constraints (Figure 46). Select the icon representing a node with no translational or rotational degrees of freedom. Cross Link will proceed to set the boundary conditions on all selected nodes. The frame geometry is now complete. If element releases are required for any elements, select the elements and then select the element tool using the right mouse button (The spring tool, the point load tool and the UDL tool all behave in a similar manner). A window will open presenting the available release options for an element (Figure 47). The convention for placing releases is based on the element's high and low node numbers. Note that the elements are displayed as dotted lines when they do not have properties assigned to them. In order to set the element properties, select the desired elements and select the property tool with the right mouse button. A window will prompt you to enter the required properties for the selected elements. - 51 - File Edit Settings nacro Laois halo ■^1 (Untitled)^ F 4 I 1 f Too(29500.0 : 9500.0) EDIP I^ 0 1  A ^ A  ^.__.^. P 0 (i)2 ''' ..-6L::-45_.;:::49.: () 1 0...: ...22........?A...?±...*K--4F-1:-.;(07.... -*Fs - . 03?. ....4P. • • ...30 31 Ill ^4 ;9'6:^: 41 1'44i2^_.i. (ifig  ,:iiii .4jili 40'45i , ,._. [ .  ^i ■ ^ •  ^III lg. 1 of = ci A. 0 I' I-1 III  IIII^ ■ 11111111, i J^.^I Watch Window^ ) 4 I i ^r Figure 46. Placing Node Boundary Conditions. Constraints are placed by selecting the node tool with the right mouse button. The selected nodes (below) will be affected by the selection. Elle edit lettings Macro 'polo Halo .^ .J^■^I (Untitled)^ I 4^Et - Tools (25500.0 : 17500.0) Zo ED 0--0 1^2  El: (i)?-----F5` ---*F 1,•^• l'•,....̂ 24  :^1 :'--.. !8...:: 40. •::619: 2p........at. ^2.7^2B .1^.'219- .^30 ^31^32 ..4102.-t-- 4:1>^• -t.^-^•• Ar.. ... 407 .^1,....rl.... ___403^.0^436 I^'-... ^...-^; ii- •^i iis.:^. ii- ..^, iii. : I ii .-.^: 5 eai  1 r ^it?' )41:4111 4_... 0^ i ^(9^w^t 1 ge ^ W s ciA. 01' r1 1^ '1111111111iJ .^I Watch Window^ 1 4Itl in . Figure 47. Setting Element Fixity. Element fixity is specified by selecting the element tool with the right mouse button. Exporting a Structure to the ANSYS Finite Element Programme In order to export a structure to the ANSYS finite element programme, a macro must be written to extract the node and element data from the Cross Link database and to write it to an ASCII file in a format readable by ANSYS. Nodes are specified in an ANSYS data file using the N command which has the following syntax: N,nodenumber,x_coordinate,y_coordinate[,z_coordinate] Elements are specified using the E command. The ANSYS E command automatically takes care of the element numbering so its syntax is: E,lo_node_number,hi_node_number Nodal boundary conditions are placed using the D command. Its syntax is: - 53 - D,node_number,dof,displacement [„„dof2,dof3 where: dof, dofl and dof3 can be either UX,UY or ROTZ, displacement = 0.0 For simplification, we will assume that only the node, element and boundary condition information must be provided for ANSYS. To start, using an ASCII editor open a file called 'ansys.bob'. Three functions are required to write the nodes, the elements and the boundary conditions to a file. The first function will be called writeNodes(). It takes one parameter, the file handle, and is specified as follows (review Appendix A for an overview of the BOB programming language and the Cross Link library functions): // writeNodes - writes all node information to file writeNodes(file;nodeNumber,x,y) nodeNumber = NodeFirst(); while(nodeNumber)( x = NodeGetX(nodeNumber); y = NodeGetY(nodeNumber); fwrite(file,"N,",nodeNumber, 11,11,x,11,11,y,11\n"); \\ '\n' is linefeed nodeNumber = NodeNext(); To extract the nodes, a call is first made to the NodeFirst() function which returns the number of the first node in the node database or nil if there are no nodes. The x and y coordinates are obtained using the NodeGet?() function. The fwrite 0 function is then used to write the information to file in an ANSYS compatible format (note thatfwrite 0 can take a variable number of parameters). The NodeNext() function is then called to get the next node in the database. This is all performed inside a while loop until NodeNext() returns a value of nil. The function writeElements() can be implemented using a procedure identical to writeNodes() except this time the two nodes points for the element are required. These are obtained using the ElementGet??Node 0 functions: // writeElements - writes all node information to file writeElements(file;elementNumber,loNumber,hiNumber) C elementNumber = ElementFirst(); while(elementNumber)( loNumber = ElementGetLoNode(elementNumber); hiNumber = ElementGetHiNode(elementNumber); fwrite(file, "E,", loNumber, 11,11, hiNumber, "\n"); - 54 - elementNumber = ElementNext(); To write the node boundary conditions, the node database must be traversed again, this time to retrieve the degree of freedom (dot) code for each node (using NodeGetD0F0). This code is compared with a set of constants which represent each allowable degree of freedom for a node. For example, the constant ID _101 represents a node with no allowable x translations or z rotations. The value of ID 101 is 5 which is obtained from the binary representation 101. Hence logical operators (such as a bitwise OR [ I ]) can be used on the dof code to determine if a particular dof is free or not. For example, to set the x dof in an existing code (which may or may not have the code set) the dof can be OR'd with the ID 100 code (ie. dof = dof I ID 100). The writeBoundwyCond() function is implemented as follows: writeBoundaryCond(file;nodeNumber,dof) num = NodeFirst();while(num)(// get the node degree of freedomdof = NodeGetD0F(num); if(dof == ID_100)fwrite(file,"D,",num,",UX,0.0\n");else if(dof == ID 110)fwrite(file," - 0,",num,",UX,0.0„„UY\n");else if(dof == ID 111)fwrite(file,"D,",num,",UX,0.0„„UY,ROTZ\n"):else if(dof == ID 101)fwrite(file,"D  ,",num,",UX,0.0„„ROTZ\n");else if(dof == ID_001)fwrite(file,"D,",num,",ROTZ,0.0\n");else if(dof == mom)fwrite(file,"0,",num,",UY,0.0\n");else if(dof == ID 011)fwrite(file,"0 ,",num,",UY,0.0„„ROTZ\n"); num = NodeNext(); All three functions along with the following required main() function are placed in the same ASCII file (main() usually appears first). The main() function will open the ANSYS ASCII data file (harded coded to be 'test.dat') and call the three functions to write the node, elements and boundary conditions respectively: main(;filehandle) // open a file (test.dat) for writingfilehandle = fopen("test.dat", "w"); // write the nodes, elements and BC'swriteNodes(filehandle);writeElements(filehandle);writeBoundaryCond(filehandle); - 55 - // close the file fclose(filehandle); File Edit Eettines Macro tools Help 1(Untitled>^ 111T1- Tools( 0400 _0 :^11200_0) MI E) • .^. .^.^. • •^1188BEW-8888888 Extutu,^m_iuty^filiL.._ .38888881,188388E4188888-38868138888388EBB88883a8tO888803111.888 , Asu File nano: 1ANS-OUT.BOB^1.^.^. • •^• • .^ . .^. Directors: C:NXLINKNMACROS Files:^Directories: C9.41r,:;:iANS-IN.BOBANS-OUTDEMO.BOBERASE.BOB 1;1 . .C A:^][^B:^]C^C:^3 1111 X 0 JL.T. ,0 PREWAR^I ca---1^I^I^11° 11) I • I^ Watch Window^ 4^t l 1^ r, . Figure 48. Running a Macro in Cross Link. Let's return back to the frame problem. The 'ansys.bob' macro can be run from Cross Link by selecting the Macro...Run macro menu option which will present a listing of all macro files (*.bob) in the current directory. Select the ansys.bob file and then the OK button (Figure 48). The frame will be written to the file 'test.dat' which is presented in Figure 49. Shown in Figure 50 is the frame as interpreted by the ANSYS preprocessor, PREP7. Listed in Appendix A is a more complete ANSYS file export macro (ANS-OUT.BOB) which comments the data file and also includes a dialog box to get the name of the destination data file. Also presented is a listing for a macro to import a commented ANSYS data file (ANS-IN.BOB). Basicly, this macro uses the fread 0 function to read in a line of data from a file and the token() function is used to parse the fields from the string. It takes a two parameters; the first is the string - 56 - N,^1, N,^2,N,^3, 0.0000, 0.00000.0000, 8500.00000.0000, 10000.0000 E,^2,E,^7,E, 8, 789 E, 7, 20E, 8, 20E, 8, 21N, 4, 28000.0000, 0.0000 E,^9, 10 E,^9,^21N, 5, 28000.0000, 8500.0000 E, 10, 11 E, 9, 22N, 6, 28000.0000, 10000.0000 E, 11, 12 E, 10, 22N, 7, 2000.0000, 8500.0000 E, 12, 13 E, 10, 23N, 8, 4000.0000, 8500.0000 E, 13, 14 E, 11,^23N, 9, 6000.0000, 8500.0000 E, 14, 15 E, 11,^24N, 10, 8000.0000, 8500.0000 E, 15, 16 E, 12, 24N, 11, 10000.0000, 8500.0000 E, 16, 17 E, 12,^25N, 12, 12000.0000, 8500.0000 E, 17, 18 E, 13,^25N, 13, 14000.0000, 8500.0000 E, 18, 19 E, 13, 26N, 14, 16000.0000, 8500.0000 E, 5, 19 E, 13, 27N, 15, 18000.0000, 8500.0000 E, 1, 2 E, 14, 27N, 16, 20000.0000, 8500.0000 E, 2, 3 E, 14, 28 N, 17, 22000.0000, 8500.0000 E, 3, 7 E, 15, 28N, 18, 24000.0000, 8500.0000 E,^3, 20 E, 15, 29N, 19, 26000.0000, 8500.0000 E, 20, 21 E, 16, 29N, 20, 2000.0000, 10214.2861 E, 21, 22 E, 16, 30N, 21, 4000.0000,^10428.5713 E, 22, 23 E, 17, 30N, 22, 6000.0000, 10642.8574 E, 23, 24 E, 17, 31N, 23, 8000.0000,^10857.1426 E, 24, 25 E, 18, 31N, 24, 10000.0000,^11071.4287 E, 25, 26 E, 18, 32N, 25, 12000.0000,^11285.7139 E, 26, 27 E, 19 , 32N, 26, 14000.0000,^11500.0000 E, 27, 28 E, 6,^19N, 27, 16000.0000,^11285.7139 E, 28, 29 E, 5, 6N, 28, 18000.0000,^11071.4287 E, 29, 30 E, 4, 5N, 29, 20000.0000,^10857.1426 E, 30, 31 D, 1,UX,0.0,,,,UY,ROTZN, 30, 22000.0000, 10642.8574 E, 31, 32 D, 4,UX,0.0,,,,UY,ROTZN,^31, 24000.0000,^10428.5713 E, 6, 32N,^32, 26000.0000,^10214.2861 Figure 49. The resulting ANSYS data file for the frame. to parse and the second is a string listing all possible field delimters in the string (the ANSYS delimiter is a comma [,]). The first call to token() returns the first parameter in the string. To parse the remainder of the string, successive calls are made to token with no string passed (ie. tok = token(0,delimiter)) until the nil is returned. Thestrcmp 0 and val() functions can be used to compare a string and convert it to a number respectively. offina.0111111Liturmin ANSYS 4.4 UNIV VERSION MAR 23 1990 10:34:2R FRET'? ELEMENTS TYPE NIIM BC SYMBOLS ZU =1 DIST=n400 XF =14000 YF =5750  Cross Link to ANSYS Transfer Figure 50. Example Frame Exported to the ANSYS Programme. 4.5 Extending Cross Link Several modifications could be made to Cross Link's editing environment and macro language. This section discusses some alterations that could be done to enhance the editing capabilities and also extend the preprocessor to a postprocessor. Recognition of the Physical and Finite Element Models Currently, a shortfall with the preprocessor is the fact that analysts still have to describe a structural model in terms of nodes and elements. No feature is yet provided to model a complete structural component such as a continuous beam, as a single entity and still recognize that it is composed of multiple nodes and elements. Structural analysis is performed at a level closer to the finite element model rather than the physical model (Figure 51). Clearly, an alternate data modelling technique is required that recognizes the requirements of the physical model and the finite element model. The physical model is most intuitive for structure description because it explains the structure - 58 - 1PREPROCESSING MODEL PHYSICAL MODEL FINITE ELEMENT MODEL in terms of it structural components (ie. beam, column, slab). The finite element model provides a method of discretizing the physical model into data which is then used in forming the mathematical model of the structure. Figure 51. The Physical and Finite Element Structural Models To move from the finite element based model and back towards the physical model, modifications have to be made in the way nodes and elements are currently represented. Shown in Figure 52 is an alternate implementation of the element container which has been renamed to an assembly container, SO_ASSEMBLY CONTAINER. The assembly container now holds assembly objects (SO_ASSEMBLY) which are container classes that model both the physical and finite element views of "vector type" elements such as beam and columns or "area type" elements such as slabs and walls. As shown in the figure, the assembly object will always contain, at the least, one element (SO _ELEMENT) which would represent the physical view of the structural component (the beam or column). Finite elements could then be added to the container (as SO _ELEMENT's) - 59 - but would be distinguished from the corresponding physical model element. Numerous other objects such as custom components or custom sub-assemblies (which are again container classes) can also be added to the assembly to model loads, boundary conditions or section table objects. Every component and sub-assembly in the assembly container has to behave according to a common message protocol defined by the container. Sub-assembly components could also define a message protocol to communicate object with the sub-assembly container. ^..... ^. . ..SO_GRAPHIC_CONTROL . . .^Generic container^' class • . •^•^• . . . .. . . .. . . . . . .., . . . .. .^ . ..... .. . . .. SO_ASSEMSLY_CONTROL^ 1^ • ^ Cy . SO_ASSEMILY^' . i^+ contain., oft.. for 0__________^Container class for 0^SO_ELEMENT • assembly objects assembly components•• '' . „ . . . • . . . • . • • • - . , • " CUSTOM COMPONENTS • • .^. •^. • • CUSTOM • SUR-ASSEMILIES •• •• •• • •^• Figure 52. Alternate Implementation of the Element Container. The element container is now called an assembly container. For users of the application, most structural modelling would occur on the physical model level. However, a user would also have the ability to enter into a finite element model mode which would allow assemblies to be selected and discretized into finite elements. Returning to the physical model, all finite elements would disappear. An editing operation such as moving an assembly would occur on the physical model level; all finite elements would automatically be moved (so instead of selecting 10 elements representing one continuous beam or assembly, the user would select one assembly). • . „^. • ' • . • • - 60 - gusset plate object point load object ...------ distributed load object A......-- shear connection object the assembly object N section object moment connection object The concept of an assembly container that holds sub-assemblies and components could ideally serve as an extension of the preprocessor to a design programme (Figure 53). Objects such as connections or web stiffeners could be added to an assembly container to create detailed assemblies. Using polymorphism, generic messages such as DesignYourself would be dispatched from the assembly container to all objects. The objects in the container would then respond to a message such as this and proceed to design themselves. Because of the two way interaction between the container and the object, the object would also have the capability to query the container for required design information. For example, a moment connection object may query the assembly object to obtain the design moment and shear for the connection. Figure 53. Extending Assemblies for Postprocessing and Design The benefits of this approach must be emphasized. Firstly, this model recognizes the needs of the end user of the system - a compromise in modelling capability between the physical and finite element views. Secondly, all assemblies, sub-assemblies and components are developed and debugged as separate entities, each adhering to the interface-implementation concept. This results in a set of objects that should be more resilient to changes made in the system. Finally, assemblies now have a very dynamic appearance because of the ability to modify and enhance behavior simply by adding components. Future objects can easily be implemented as long as they adhere to the message protocol defined by the assembly container. - 61 - Extending the Macro Language Implementation of the aforementioned assembly concept would require modifications to the interface between the macro language and the Cross Link kernel. This is mainly because the containers are now nonhomogenous because they can hold many different types of objects. The existing implementation exploits the fact that the node and element containers are homogeneous. For example, the BOB library functions ElementFirstOlElementNext0 (see Appendix A) are used to traverse the element container by initializing and incrementing an internal pointer. Both functions return an integer value representing the current element number. // example function to print all element fixity codes PrintFixity( ; elementNumber,fixity) C // get the first element • elementNumber = ElementFirst(); while(elementNumber)( fixity ElementGetFixity(elementNumber); print("Element ",elementNumber,"^",fixity); // get the next element in the list elementNumber = ElementNext(); } Clearly, the above system used to manipulate the element container could not work adequately in an assembly container based system. Functions such as ElementFirst() and ElementNext() could still be implemented but the internal representation of the assembly container would not be fully accessible to macro users. Really, a macro user should have the ability to edit the contents of any object in the container. A feature such as this could be implemented using the class mechanism supported by the macro language. Pre-built classes could be designed into the language that would allow duplication of the objects data and provide a set of methods within the class to manipulate the data. Additional language keywords could also be created to allow determination of class types (in the existing implementation of the macro language, classes do not know their type). For example, an assembly container may be manipulated with a macro in the following way: // get the first object in the container object = AssemblyFirst()while(object)( // compare the object string typeif(type(object,"Assembly"))(subObject = ObjectFirst(object);while(subObject)C// look for element objectsif(type(subObject,"SO_ELEMENT"))f// we've got an element stored in the assembly elementNum = subObject->Number();print("Found element number ",elementNum); - 62 - else if (type(subObject,"SO_PROPERTY"))(// we've get a property object in the assemblyInertia = subObject->GetInertia();Area = subObject->GetArea(); subObject = ObjectNext(object); ) // get the next object in the container object = AssemblyNext(); Here, the ElementFirstOlElementNext0 functions have been replaced by the AssemblyFirstOlAssemblyNext0 functions. These functions now return a handle which now represents a reference to any type of object stored in the container. A special language keyword, type, is then used to determine the class type of the object. The functions ObjectFirstOlObjectNext(), which take an object as a parameter, can then be used to determine the contents in an assembly object. The above example looks only for element (SO_ELEMENT) and property (SO PROPERTY) objects. Once the object's type is determined, member functions that are internally attached to the object can be used to manipulate the object. 5 CONCLUSIONS This thesis has examined the use of object-oriented programming techniques in the development of engineering applications. The paradigm is very well suited to large, complex software applications where issues such as encapsulation, code reusability, portability and maintainability are important. These aforementioned features can be implemented using conventional paradigms such as structured programming, but only through programmer discipline. For example, most procedural languages provide only very limited support in the language syntax for concepts such as information hiding. Conversely, object-oriented languages imbed concepts such as information hiding rules directly into the language syntax and let the compiler provide the enforcement. Consequentially, software becomes more reliable and programmers become more productive because the compiler is now used as a more active tool in the development process. Cross Link, a universal structural analysis preprocessor, provides an easy to use, interactive editing environment that, through the use of a macro programming language, links bi-directionally with any structural analysis programme. The unique macro facility also gives end users the exciting ability to customize the preprocessor to their own requirements, thus providing unprecedented flexibility. Conceivably, the macro language could also be used to provide an electronic link between structural design and drafting. Traditionally, this communication link is done through hand drawn sketches; engineers describe the geometry of a structure in their analysis and design programmes, produce a sketch of the final product and then pass this on to drafting personnel. These people then have to re-enter the information back into a CADD programme for final detailing. Cross Link could be used to provide a smoother, more effective communication link between engineer and draftsman. The link may be simple as a wire frame model or as complex as a fully detailed and dimensioned frame. Features such as these could be implemented using a drawing exchange standard such as IGES or DXF. 6 REFERENCES [1] Betz, David. Your Own Tiny Object-Oriented Language. Dr. Dobb's Journal, September 1991, pp.26-33. [2] Blair, Gordon. et al. 1991. Object-Oriented Languages, Systems and Applications. Reading, London:Pitman Publishing [3] Booch, Grady. Object Oriented Development IEEE Transactions on Software Engineering, Volume 12, Number 2, February 1986, pp.211-221. [4] Booch, Grady. 1991. Object Oriented Design With Applications. CA:Benjamin Cummings. [5] Borland International Inc. 1990. Turbo C+ + Programmer's-Guide. [6] Coad, Peter. And Yourdon, Edward. 1990. Object Oriented Analysis. NJ:Prentice Hall. [7] Dale, Nell. and Orshalick, David. 1983. Introduction to PASCAL and Structured Design. MA:D.C. Heath and Company [8] Dupont, G. et al. A Functional and Object-Oriented Design Approach, Fourth International Conference on Computer Aided Software Engineering, December 1990, pp. 356-372. [9] Duntemann, Jeff. Structured Programming. Dr. Dobb's Journal, May 1990, pp.141-145 [10] Elbury, Kevin M. Source Code for the Cross Link Universal Structural Analysis Preprocessor. 1992, University of British Columbia, Vancouver, B.C., Canada. [11] Hoy, Patrick. A Comparison of Object-Oriented and Structured Development Methods. ACM SIGSOFT, Volume 15,Number 1, January 1990, pp.44-48. [12] LaLonde, Wiif R. and Pugh, John R. Specialization, Generalization and Inheritance: Teaching Objectives Beyond Data Structures and Data Types, SIGPLAN Notices, Volume 20, Number 8, August 1985, pp.88-92. [13] Lee. H.S. and Arora, J.S. Object-Oriented Programming for Engineering Applications. Engineering With Computers. Volume 7, 1991, pp.225-235. [14] Lieberman, Henry. Using Prototypical Objects to Implement Shared Behaviour in Object Oriented Systems. Proceedings of the Conference on Object-Oriented Programming Systems, Languages and Applications (00PSLA '86). 1986, pp. 214-223. [15] Mullin, Mark. 1989. Object Oriented Program Design. Reading, MA:Addison-Wesley. [16] Pascoe, Geoffrey A. Elements of Object Oriented Programming. Byte, Volume 11, Number 8. August 1986, pp.139-144. - 65 - [17] Snyder, A. Encapsulation and Inheritance in Object Oriented Programming Languages. Proceedings of the Conference on Object-Oriented Programming Systems, Languages and Applications (00PSLA '86). 1986, pp. 38-45. [18] Sommerville, Ian. 1989. Software Engineering. Reading, MA:Addison-Wesley. [19] Stroustrup, Bjarne. 1986. The C+ + Programming Language. Reading, MA:Addison-Wesley. [20] Taenzer, David., Murthy, Ganti and Podar, Sunil. Problems in Object-Oriented Software Reuse. Proceedings of the Third European Conference on Object-Oriented Programming (ECOOP 89). 1989. pp.25-38 [21] Zinc Interface Library Programmer's Reference (Version 2.0), Zinc Software Incorporated, Pleasant Grove, Utah. APPENDIX A CROSS LINK MACRO LANGUAGE FUNCTION REFERENCE Cross Link Macro Language Function Reference bel  Cross Link^ Programmer's Reference Table of Contents 1 THE CROSS LINK MACRO LANGUAGE^ 71 1.1 Basics^ 71 1.2 Variables and Expressions^ 72 Data Types 72 Expressions^ 73 1.3 Program Control Statements^ 74 1.4 Objects and Classes 75 2 CROSS LINK PROGRAMMER'S REFERENCE^ 77 2.1 Programming Constants^ 77 2.2 Input / Output Functions 79 fclose()^ 79 fopen() 80 fread() 81 fwrite()^ 82 getc() 82 putc() 83 print()^ 83 2.3 Math Functions^ 84 abs() 84 acos ( ) / asin ( ) / atan ( )^ 84 atan2()^ 85 cos() / sin() / tan()^ 85 exp() 85 hypot()^ 86 log() / log10() 86 pow() / pow10()^ 87 sqrt()^ 87 2.4 String Functions 88 strcmp() 88 token()^ 89 val() 90 2.5 Cross Link System Functions^ 91 SetGrid()^ 91 New() 92 Prompt() 93 PromptYesNo()^ 94 Repaint() 95 SetLimits() 95 Speaker()^ 96 2.6 Node Functions 97 NodeErase() 97 -71- Cross Link^ Programmer's Reference NodeFirst() / NodeNext() NodeGetDOF() / NodeSetDOF() NodeGetX() / NodeGetY() NodeHigh() NodePut() NodeSelect() NodeSelected() NodeSetX() / NodeSetY() NodeToggleSelect() NodeUnSelect() 2.7 Element Functions ElementErase() ElementFirst() / ElementNext() ElementGetFixity() / ElementSetFixity() ElementGetLoNode() / ElementGetHiNode() ElementSetProp() ElementHigh() ElementPut() ElementSelect() ElementSelected() ElementToggleSelect() ElementUnSelect() 3 EXAMPLE APPLICATIONS 3.1 Demonstration Program 3.2 ANSYS File Transfers ANS-IN.BOB ANS-OUT.BOB 98 99 100 100 101 102 102 103 103 104 105 105 105 106 107 108 108 109 110 110 111 111 112 112 114 114 117 Cross Link^ Programmer's Reference 1 THE CROSS LINK MACRO LANGUAGE The BOB macro language is a weakly typed, object oriented programming language that users of the Cross Link Preprocessor have access to within an editing session. The uses of the language are limitless: importing/exporting data files, manipulating the Cross Link node and element databases,  and parametric structure definition to name a few. BOB has several features that make it unique as a programming language. It contains flavours of C, C+ + and LISP although its syntax is almost identical that of C. Being object oriented, it supports class definitions and inheritance. In a weakly typed language, basic data types such as integer numbers, floating point numbers and character strings are never explicitly typed by the programmer as integers, floats, or strings. This is advantageous since it makes the language more flexible and easier to use. 1.1 Basics The basic program unit inside a BOB program is the function. Every BOB program requires a function called main() that must exist somewhere in the program file. A functions can take any number of parameters and perform operations on those parameters. The function may directly modify the values passed into it or it may only use them for calculations. Functions also have the ability to return a value. Hence a call to a function usually appears as an assignment. main( ; x, x_squared) x = 5; 4x squared = Square(x); // call the Square() function // Function: Square(z) // - returns the square of z Square(z ; tmp)^// note x is a parmeter, tmp is a local variable tmp = z * z;^// calculate the square... return(tmp); ) Figure 1. A BOB program to calculate the square of a number. The function Square does the calculation. From the example program in Figure 1, several observations can be made: -73- Cross Link^ Programmer's Reference • The function main() has two local variables, x and x squared which are declared after the semicolon in declaration of main(). • Any function must enclose all of its associated code in curly braces {}. • A semicolon (;) ends every line in which there is an assignment. • The Square() function takes one parameter, x (declared as z). • The Square() function has one local variable, imp, declared after the semicolon in the function definition. • The Square() function returns the value of x * x. • Program comments are place by preceding the comment with two slashes 1.2 Variables and Expressions Data Types As mentioned in the introduction, BOB is an untyped language. Thus as a user of BOB, you are not required to explictly declare the type of any variable. However, you must be aware of the basic internal representation of data types in order to use the language correctly. When a variable is declared, its default data type is type nil. Only when an assignment is made to the variable, is its type set. Shown in Figure 2 is an example program emphasising BOB's internal treadment of data types. From this example we can make the following observations: • Variables are of type nil before they they are used. • In Part A, i and j are typed as integers because no decimal point appears in the number 2 or 5. The result of the integer division, 5 / 2, is 2. Cross Link^ Programmer's Reference main( ;i,j,k) // Part A: Division using integers i = 5;^// represented as integer j = 2; k = i / j;^// result is 2 // Part B: Dividision using floats (deimals) = 5.0;^// represented as float j = 2.; // also represents as float k = i / j;^// result is k = 2.5 Figure 2. A BOB program used to compare calculations using integers and floating point (decimal) numbers. • In Part B, the variables i and j change type from integer to floating point (legal in BOB) as indicated by the decimal point (2.0). Here the result is different: 5.0 / 2.0 = 2.5. • If the division involved a floating point number (ie i = 5.0) and an integer (ie. j = 2.0) the result would a float (k = 2.5). • The above rules are applicable to all other basic mathematical operations. Expressions Listed in Figure 3 are the basic expressions supported by BOB. Since all of these expression are a subset of the C programming language, instructions and examples on their use can be found in any C programming reference (ignore anything to do with pointers). -75- <expression> II <expression> <expression> && <expression> <expression> I <expression>1 <expression> - <expression> <expression> & <expression> <expression> == <expression> <expression> I= <expression> <expression> < <expression> <expression> <= <expression> <expression> >_ <expression> <expression> > <expression> <expression> « <expression> <expression> » <expression> logical OR logical AND bitwise OR bitwise XOR bitwise AND equal to not equal to less than less than or equal to greater than or equal to greater than shift left shift right <expression> + <expression> <expression> - <expression> <expression> * <expression> <expression> / <expression> <expression> % <expression> plus minus multiply divide remainder -<expression> !<expression> <expression> ++<expression> --<expression> <lvalue>++ <lvalue>-- unary minus logical negation (NOT) bitwise negation preincrement predecrement post increment postdecrement Cross Link^ Programmer's Reference <expression>,<expression> ^ comma expression <lvalue> = <expression> assignment <lvalue> += <expression> ^ assign sum <lvalue> -= <expression> assign difference <lvalue> *. <expression> assign product <lvalue> 1= <expression> ^ assign quotient <test-expression> ? <true-expression> : <false-expression> conditional operator Figure 3. Operations supported by BOB. An <lvalue> is a left hand side value meaning the variable must be able to have the result of an expression assigned to it. 1.3 Program Control Statements BOB contains all the program control statements of the C language (except for the switch statement). Listed in Figure 4 are the four program control statements used by BOB. Cross Link^ Programmer's Reference if( <test-expression> ) <then-statement> [else <else-statement> ] uhile(<test-expression>) <body-statement> do <body-statement> uhile(test-expression); for(<init-expression>;<test-expression>;<increment-expression>) <body-expression> break; continue; return(<result-expression>); Figure 4. Program control statements supported by BOB. 1.4 Objects and Classes BOB supports class definitions and single inheritance. A class can be used to combine both data (called member data) and the functions (called member functions) that operate on that data into a single entity. Generally a complete class system includes two components. The first is the class template which defines the member data and the member functions of the class. Using inheritance, classes are able to inherit the member data and functions of other classes in order to extend or modify them. The second component of a class system is the implementation or definition of the member functions. These are coded outside of the class template; they look like regular functions except the function name is preceded by the class to which the function belongs. However, member data appears global to the member functions so member data is never passes as an argument to a member functions. The syntax for class definition is shown in Figure 5. The class definition serves as a template for the physical definition of an object; an object is an instance of a class. An object is instantiated using the new operator. Member functions within the object are then referenced using the -> operator. However, all member data in a class definition is private so it cannot be referenced using the -> operator. Therefore, member data is typically referenced by users of the object via members functions that set or retrieve the value of member data. Figure 6 shows the syntax for creating objects and accessing them. -77- Cross Link^ Programmer's Reference Class Definition: class <class-name> [: <base-class-name>] C <member-definition> <member-definition> where <member-definition> is any/all of the following: <variable-name>; static <variable-name>; Ounction-name>((formal-argument-list>1); static Ounction-name>((<formal-argument-list>l ); Member Function Definition: <class-name>::<member-function>([<argument-list> ; <temporary-argument-list>]) C <statements> Figure 5. Class definition syntax. Object Creation: <object-name> = new <class-name>((<constructor-arguments>3); Object Access: <object-name>-><function-name>((<arguments>1) <object-name>-><data-name >; Figure 6. Object creation and access syntax. Every object usually has a constructor as one of its member functions. Constructors have the same name as the class and are used for initialization on any member data. They are automatically called when an object is instantiated using the new keyword. Figure 7 shows an example implementation of a class system to represent a point in space. // The Point class definition class Point C x,y; Point(x,y); Move(dx,dy); GetX(); GetY(); // the coordinates of the point // Constructor // move the point // get the data -78- Cross Link^ Programmer's Reference // Constructor Point::Point(a_x,a_y) x = a_x; Y = a_Y; // move the point a distance (dx,dy) Point::Move(dx,dy) C x += dx; y += dy; // get the x and y coordinates of point Point::GetX() C return x; Point::GetY() C return y; ) // Example implementation of a Point class main( ; aPoint, x) C // instantiate a Point object at (0,0) aPoint = new Point(0.0,0.0); // constructor is automatically called // offset the point a distance of (10.0,10.0); aPoint->Move(10.0,10.0); // inquire about its coordinates x = aPoint->GetX(); Figure 7. Example implementation of class Point. -79- Cross Link^ Programmer's Reference 2 CROSS LINK PROGRAMMER'S REFERENCE 2.1 Programming Constants Several constants are pre-coded into to the system. These are listed in the following table: Name Value Comments TRUE FALSE 0 1 Generally used as a return value from some functions. PI 3.14159265 ID 000 ID 001 ID 011 ID 111 ID 101 ID 100 ID 010 N/A These are node degree of freedom codes used by NodeGetD0F0, NodeSetDOF() and NodePut() ID_FF ID_PP ID_FP ID_PF N/A These are element fixity codes used by^ElementGetFixity(), ElementSetFixity(),^and ElementPut(). Cross Link^ Programmer's Reference 2.2 Input / Output Functions fclose() Synopsis fclose(file) file - file handle Remarks fclose() closes the file associated with the file handle file. Example outputfile = fopen("test.dat","rb"); fctose(outputfite); Cross Link^ Programmer's Reference fopen0 Synopsis fopen(fname,mode) fname - the file name mode^- the access mode for the file Remarks Use fopen to perform I/O to a file. fopen() returns the handle to the file frame opened. Valid modes are any combination of the following access modes and file translation modes: Access Modes for File I/O String^Interpretation "r"^Open file for read only operations "w"^Open a new file for writing. Existing contents will be overwritten. iiai,^Open a file for appending. "r +"^Open an existing file for read and write operations. Error it the file does not exist.,,w+t,^Create a file and open it for reading and writing. "a +"^Create a file and open it for reading and writing. File Translation Modes for File 1/0 Mode^Interpretation "b"^File is opened in binary mode. Every character is read as is without the changes described below. "t" ^File is opened in translated mode subject to the following: 1. Carriage Return-Line Feed combinations on input are translated to single linefeeds. 2. During input, the Ctrl-Z character is interpreted as the EOF character. Example -82- Cross Link^ Programmer's Reference // open test.dat for writing to outfile = fopen("test.dat 11,H0); fwrite(outfile,"This file is called test.dat"); fread0 Synopsis fread(file) file- file handle (see fopen()) Remarks Use fread to read a line from file. The line is read until a newline character (\n) is encountered. The maximum line length is limited to 255 characters. If there are no errors, fread() returns the the string read; otherwise it returns nil. Example // program to print the file test.dat to the watch window main( ; file, string) ( // open test.dat for reading file = fopen("test.dat","r"); // read the first line string = fread(file); while(string)( print(string); string = fread(file); ) ) -83- Cross Link^ Programmer's Reference fwrite() Synopsis fwrite(file,...) file- the file handle (see fopen()) Remarks Use fwrite to write data to a file. Numeric values are automatically padded with a blank space on the left hand side. Floating point numbers are output to four decimal point accuracy. Additional characters can be used to control output: \n^- new line character \t^- insert a tab character Example // open test.dat for writing to outfile = fopen("test.dat 11,110); // write some text and add to Line feeds fwrite(outfile,"\tThis file is called test.dat\n\n"); getc() Synopsis getc(fhandle) fhandle - the file handle Remarks Use getc() to read the next character from the file associated with fhandle. The function returns -1 when the end of file is reached. Example // read a character from file char = getc(file); print("Read the char: ",char," from file."); Cross Link^ Programmer's Reference putc() Synopsis putc(char,thandle) Remarks Use putc() to write the character char to the file associated with (handle. Example // write a character to file putc("a",file); print() Synopsis print(...) Remarks Use print() to print information to the Watch Window inside Cross-Link. Print takes any number of data types and is capable of distinguishing between different data types. This function is useful for debugging and displaying information to the user. Example print(ncount," nodes selected"); Cross Link^ Programmer's Reference 2.3 Math Functions abs() Synopsis abs(number) number^- the number Remarks abs() returns the absoulute value of number. Example value = -10.3454 value = abs(value); // value = 10.3454 acos() / asin() / atan() Synopsis acos(x) asin(x) at an(x) Remarks Use acos(), asino, atano to compute the arc cosine, arc sine and arc tangent of argument x. For acos() and asin(), x must be between -1 and 1. The returned angle is in RADIANS. Example angle = acos(0.5); // angle = P1/3 Cross Link^ Programmer's Reference atan2() Synopsis atan2(y,x) Remarks atan2() returns the arc tangent of y/x in radians. Example angle = atan2(y,x); cos() / sin() / tan() Synopsis cos(theta) sin(theta) tan(theta) Remarks Use cos(), sin(), and tan() to compute the cosine, sine and tangent of angle theta (in RADIANS) Example vat = cos(PI); // yal = -1 exp() Synopsis exp(x) Remarks Use exp() to calculate the exponential of x. Example eyal = exp(10.345); -87- Cross Link^ Programmer's Reference hypot() Synopsis hypot(x,y) Remarks Usehypot() to compute the length of the hypotenuse of a right angle triangle given the length of both sides, x and y. Example length = hypot(3.0,4.0);^// length = 5.0 log() / log10() Synopsis log(x) log10(x) Remarks Use loge and log10() to calculate the natural logarithm and logarithm to the base 10 respectively of argument x. Example y = log(2.0); // t = 0.693147 Cross Link^ Programmer's Reference pow() / pow10() Synopsis pow(x,y) pow10(z) Remarks Usepow() to calculate the value of x raised to the power of y. Usepow100 to raise 10 to the power of z. Example x = pow10(2);^// x = 100.0 y = pow(2,4);^// y = 16.0 sqrt() Synopsis sqrt(x) Remarks Use sqrt0 to compute the square root of value x. If x is less than zero an error will occur; Example y = sqrt(abs(-2.0);^// y = 1.414 Cross Link^ Programmer's Reference 2.4 String Functions strcmp() Synopsis strcmp(stringl,string2) strcmp (stringl ,string2,n) stringl^- the strings to be compared string2 n^- number of characters to compare Remarks The first function compares stringl and string2 lexigraphically. The second function compares the first n characters of stringl and string2. Both functions are case sensitive. strcmp () returns a number less than, equal to, or greater than 0, depending on whether stringl is less than, equal to, or greater than string2, respectively. Example if(strcmp(token,"Node") == 0) print("The token is a 'Node'"); if(strcmp("Kevin Etbury","KevinEtbury",5) == 0) print("First 5 characters are the same!); Cross Link^ Programmer's Reference token() Synopsis token(string,delimiter) string delimiter Remarks - the number - a string containing the delimiting characters Use the token() function to parse the records out of a delimited string. The first argument, string, is a character string containing all the delimited tokens. The second string, delimiter, is a string describing the set of characters that delimit the tokens. In general the token() function must be called several times to completely parse string. The first call to token() includes the complete string that requires parsing. Subsequent call to token() must pass 0 as the first parameter to indicate that parsing is still to be done on the old string. However, every call still requires the delimiter string (which can be changed between calls). token() returns nil when there are no more records to parse. Example // parse each of the records from a string containing the // following format (ANSYS Node command): //^N,node_num,x,y,z // delimiter^11,11;^ // delimiter is a comma string = "N,12,123.4,232.23,0.0"; // initialize the token parser strtok = token(string,delimiter); // check the first token to see if it is a node string if(strcmp(strtok,"N")C // get the node number strtok = token(0,delimiter); num = val(strtok); // get the x, y and z coordinates strtok = token(0,delimiters); x = val(strtok); strtok = token(0,delimiters); y = val(strtok); strtok = token(0,delimiters); z = val(strtok); -91- Cross Link^ Programmer's Reference val() Synopsis val (string) string - the number in string form Remarks Use the val 0 function to convert string to a numeric value. If string contains any non-numeric characters, val() returns nil, otherwise val() returns the numeric value. Example nunber = val("123.23"); number = val(flab123"); // nunber = 123.23 // number = nil Cross Link^ Programmer's Reference 2.5 Cross Link System Functions SetGrid Synopsis SetGrid(grid_x, grid_y, x_origin, y_origin, snapflag, gridflag) grid x^- the x direction grid spacing grid_y^- the y direction grid spacing x_origin^- the x_origin of the grid y_origin^- the y_origin of the grid snapflag^- snap-to-grid flag (TRUE/FALSE) gridflag^- grid display flag (TRUE/FALSE) Remarks The SetGrid() function is used to set the grid parameters. Example // set up grid with snaps off and grid display off SetLimits(0,0,15000,10000); snapflag = FALSE; gridflag = TRUE; SetGrid(1000, 1000,0,0,snapflag,gridflag); Cross Link^ Programmer's Reference New() Synopsis New() Remarks Use New() to reset a structure by erasing all nodes and elements. Any work not saved will be lost. Example main() C 1/ start with a clean structure New(); SetLimits(0,0,15000,1000); ) -94- r 18121.,1141.14,,,k1.7 V .14 .111{114,1,ANSYS Vile Import__ Cross Link^ Programmer's Reference Prompt() Synopsis Prompt(title,prompt,value) title - the title for the dialogue box prompt^- the prompt string placed within the box value^- the initial value to be edited (integer, float or string) Remarks Prompt() opens a dialog box centered on the screen. The diaglog box consists of a title bar with title, a prompt string, a value editor and an OK button. The parameter value must be initialized (type nil is not supported) with the type of value you wish to edit (ie. string, integer or decimal number) before it is passed into this function. Prompt() returns the new value entered by the user. Example main() C filename = "test.dat" string = Prompt("ANSYS Fite Import... ","Import ANSYS filename: ",filename); // edit an integer value intval = 1; intval = Prompt("Example Integer Editor","Enter an integer: ",intval); -95- 88. nrisys Replace existing structure? Imp 1 Ho^I Cross Link^ Programmer's Reference PromptYesNo() Synopsis PromptYesNo(title,prompt) title - the title for the dialogue box prompt^- the prompt string placed within the box Remarks PromptYesNo() opens a dialog box to retrieve a Yes or No answer from the user. The diaglog box consists of a title bar with title, a prompt string, a Yes button and a No button. PromptYesNo() returns the TRUE if the Yes button was pressed or FALSE if the No button was pressed. Example main() // do we want to run the macro with a new structure? ans = PromptYesNo("ANSYS Fite Inport...","Replace existing structure?"); if(ans == TRUE) New();^// erase the existing structure... -96- Cross Link^ Programmer's Reference Repaint() Synopsis Repaint() Remarks Repaint() redisplays the contents of the structure database. Only items selected in the Settings... Display will be displayed. Example // add a node and redisplay the structure NodePut(NodeHigh(),1000,2000,ID000); Redisplay(); SetLimits() Synopsis SetLimits(left,bottom,right,top); Remarks Use SetLimits() to set the current structure limits. The limits are defined as the minimum area required to fit a structure on the screen. Cross Link will provide a viewport with at least the specified limits However, in order to maintain an aspect ratio of 1:1 the x or y limits may need to be internally adjusted. These adjusted limits are referred to as 'extents' and are stored separately from the structure limits. Note that grids will only be drawn on the specified limits. Example // define Limits big enough to hold a 10m wide by 20m high structure SetLimits(-1000,-1000,12000,22000); -97- Cross Link^ Programmer's Reference Speaker() Synopsis Speaker() Remarks Use Speaker() to sound the speaker on your computer. This is useful for debugging programs Example // select a node - make some noise if we can't find if err = NodeSelect(num); if(err == nil)( Speaker(); print("Can't find node ",num); -98- Cross Link^ Programmer's Reference 2.6 Node Functions NodeErase() Synopsis NodeErase() NodeErase(num) num - node number to erase Remarks The first function removes all selected nodes from the node database. The second function erases node num from the node database. Both functions will additionally remove any point loads, springs and elements attached to the node. Example // erase the last node in the database num = NodeHigh() - 1; retval = NodeErase(num); if(retval == nil) print("Node number ",num,"does not exist!"); else print("Node number ",nun, "deleted"); Cross Link^ Programmer's Reference NodeFirst() / NodeNext() Synopsis NodeFirst() NodeNext() Remarks NodeFirst() returns the number of the first node in the node database. It is generally used in conjunction with the NodeNext() function to traverse the node database and perform operations on individual nodes. NodeFirst() returns nil if there are no nodes in the node database. Example // function to erase nodes that are NOT selected MyErase(,num) ( num = NodeFirst();^// get the first node in the database while(num != nil)( if(!NodeSelected(num)) NodeErase(nun); // get the next 'nun' in the database nun = NodeNext(); ) ) Cross Link^ Programmer's Reference NodeGetDON) / NodeSetD0F() Synopsis NodeGetDOF(num) NodeSetDOF(num,dof) num - node number to get dof - node dof code Remarks NodeGetDOF 0 returns the degree of freedom code for node num. NodeSetDOF 0 sets the degree of freedom of node num. See NodePut() for a description of these codes. Example main() ( // change all pinned nodes to fixed nodes ModifyD0F(ID_110,1D_111); ) // function to change all nodes with dof lold_dof' with 'new_dof ModifyD0F(old_dof, new_dof; num, dof) ( num = NodeFirst(); while(num != nil)( if(NodeGetDof(nun) == old_dof) NodeSetDof(num,new_dof); nun = NodeNext(); // proceed to next number ) ) -101- Cross Link^ Programmer's Reference NodeGetX() / NodeGetY() Synopsis NodeGetX(num) NodeGetY(num) num - node to get Remarks NodeGet?() returns the x or y coordinate of node num or returns nil if node num does not exist. Example // function to calculate the distance between two nodes Length(num1,num2; dx, dy) C dx = NodeGetX(num1) - NodeGetX(num2); dy = NodeGetY(num1) - NodeGetY(num2); length = hypot(dx,dy); return(length); NodeHigh() Synopsis NodeHigh() Remarks NodeHigh() returns the number of the next available node number. Example // add a node but find out the next number we can use num = NodeHigh(); NodePut(num,100,1200,ID_000); Cross Link^ Programmer's Reference NodePut() Synopsis NodePut(num,x,y,dof) num - the node number x,y - the x and y coordinates dof - the dof code number Remarks NodePut places a node at the specified x,y coordinates with a dof degrees of freedom. Allowable dof codes are global variables set by the system. A code is specified by 'ID_' along with the x,y and rotational degrees of freedom represented by ones and zeros with 1 = free and 0 = fixed. Allowable codes are: ID_000 - free joint ID_001 - 0 rotation joint ID 011 ID 111 - fully fixed joint ID 100 ID 110 - pinned joint ID 101 If node num already exists in the node database, Cross Link will update the existing node parameters with the supplied values. Example // generate a parabolic Line of nodes k = 0.00005; for(x=0.0, x <= 10000; x += 500)(^// space nodes at 500 num = NodeHigh(); y = k * x * x; NodePut(num,x,y,1D_000);^// ID_000 is a system variable Cross Link^ Programmer's Reference NodeSelect() Synopsis NodeSelect(num) NodeSelect(left,bottom,right,top) Remarks The first function selects node num. The second function selects ALL nodes defined by a box with coordinates (leftbottom) to (righ4top). NodeSelect() returns the number of nodes selected. Use the NodeSelected() function to determine if a node is selected. Example // select all nodes within (100,100) to (500,800) count = NodeSelect(100,100,500,1000); print(count," nodes selected"); NodeSelected() Synopsis NodeSelected(num) num - node number to inquire about Remarks NodeSelected returns TRUE if node num is selected and FALSE if node num is not selected. Example if(NodeSelected(num) == TRUE) print("Node ",nun, "is selected"); Cross Link^ Programmer's Reference NodeSetX() / NodeSetY() Synopsis NodeSetX(num,x_coordinate); NodeSetY(num,y_coordinate); Remarks NodeSetX and NodeSetY are used to set the x and y coordinates of num respectively. Both return TRUE if succesful and FALSE if not. Example // set the x coordinate on node 12 num = 12; ret = NodeSetX(num,10500.0); NodeToggleSelect() Synopsis NodeToggleSelect() Remarks NodeToggleSelect() runs through the whole node database and toggles selected and unselected nodes. Example // delete all nodes except for number 5 and 7 NodeSelect(5); NodeSelect(7); NodeToggleSelect(); // flip selected/unselected nodes NodeErase(); -105- Cross Link^ Programmer's Reference NodeUnSelect() Synopsis NodeUnSelect() Remarks NodeUnSelect() unselects all selected nodes in the node database. Example // unselect all unselecded nodes NodeUnSelect(); Cross Link^ Programmer's Reference 2.7 Element Functions ElementErase() Synopsis ElementErase() ElementErase (num) Remarks The first function erases all selected elements. The second function erases element num. The return value for this function is TRUE if successful of FALSE if num does not exist. Example // erase all selected elements ret = ElementErase(); ElementFirst() / ElementNext() Synopsis ElementFirst() ElementNext() Remarks ElementFirst() returns the number of the first node in the node database. It is generally used in conjunction with the ElementNext() function to traverse the element database and perform operations on individual elements. Both functions return nil when there are no more elements in the element database. Example // traverse the element database element = ElementFirst(); while(element)( // perform any required operations on each element element = ElementNext(); -107- Cross Link^ Programmer's Reference ElementGetFixity() / ElementSetFixity() Synopsis ElementGetFixity(num) ElementSetFixity(fix_code) ElementSetFixity(num,fix_code) Remarks ElementGetFixity returns the fixity code for element num. ElementSetFixity sets the fixity code for an element. If the first is used, all selected elements are affected. If the second is used, only element num is affected (if it exists). See ElementPut() for list of fix _code's. Example // set all selected elements to pin-pin ElementSetFixity(ID_PP); Cross Link^ Programmer's Reference ElementGetLoNode() / ElementGetHiNode() Synopsis ElementGetLoNode(el_num) ElementGetHiNode(elnum) Remarks ElementGetLoNode returns the lower node number of element el_num. ElementGetHiNode returns the higher node number of element el_num. Both return nil is el num does not exist. Example // function to erase all elements that are attached to node 'nun' Spc_Erase(num; el_num o tonode,hinode) C // run through the element database el_num = Elementfirst(); while(el_num != nil)( Londe = ElementGetLoNode(el_num); hinode = EtementGetHiNode(el_num); // do we have a match?? if(lonode == nun) ElementErase(el_num); else if(hinode == nun) EtementErase(el_num); // get the next element elnum = EtementNext(); Cross Link^ Programmer's Reference ElementSetProp0 Synopsis ElementSetProp(A,Av,I) ElementSetProp(el_num,A,Av,I) el_num^- the element number A^- the Area of element el_ num (returned) Av - the Shear Area of element el_num (returned) I^- the Moment of Inertia of el num (returned) Remarks ElementSetProp() sets the sectional properties for the element. The first function set the section properties of all selected elements. The second function sets the section properties for element elnum. Example ElementSetProp(el_num,A,Av,1); ElementHigh() Synopsis ElementHigh() Remarks ElementHigh() returns the number of the next available element number. Example // add an element but find out the next number we can use num = ElementHigh(); ElementPut(num,lonode,hinode,1D_FF); -110- Cross Link^ Programmer's Reference ElementPut() Synopsis ElementPut(el_ el_num lonode hinode code Remarks - reference number for the element - the lower node number - the high node number - the fixity code num,lonode,hinode,code) ElementPut add an element to the element database. The lonode and hinode numbers must already exist. The fixity codes precode into the system as follows: ID - PP- lonode Pinned, hinode Pinned ID - FP- lonode Fixed, hinode Pinned ID - PF- lonode Pinned, hinode Fixed ID FF- lonode Fixed, hinode Fixed Example // generate parabolic line of nodes and elements Parabola(dx,dy,num1,num2,elnum) num1 = NodeHigh(); // place the starting node NodePut(num1,0,0,ID_000); // generate the line at increments of 1000 for(dx=1000.0; dx <= 11000.0; dx += 1000.)( num2 = NodeHigh(); dy = 0.00008 * dx * dx; NodePut(num2,dx,dy,ID_000); // get the next available element number and add the element elnum = ElementHigh(); ElementPut(elnum,num1,num2,ID_FF); num1 = num2; Cross Link^ Programmer's Reference ElementSelect() Synopsis ElementSelect(el_num) ElementSelect(left,bottom,right,top) Remarks ElementSelect selects an element. The first function selects an element by its number, el _num. The second function selects any elements inside a box with coordinates (left,bottom) to (right, top). Example ElementSelect(1000,1000,5000,10000); ElementSelected() Synopsis ElementSelected(el_num) Remarks ElementSelected returns TRUE if if element el num is selected of FALSE otherwise. Example // see if element 12 is selected if(ElementSelected(12) == TRUE) print("Element 12 is selected"); else print("Element 12 is NOT selected"); Cross Link^ Programmer's Reference ElementToggleSelect() Synopsis ElementToggleSelect() Remarks ElementToggleSelect toggles selected and unselected elements in the element database. Example // erase element all UNselected elements using ToggleSelect() ElementToggleSelect(); ElementErase(); ElementUnSelect() Synopsis ElementUnSelect() Remarks ElementUnSelect unselects all selected elements in the element database. Example // unselect all the elements ElementUnSelect(); -113- Cross Link^ Programmer's Reference 3 EXAMPLE APPLICATIONS Following is the BOB source code for two sample applications 3.1 Demonstration Program // ^ // File:^DEMO.BOB // Description:^Demo of the BOB programming Language // Written By:^KME // Date:^Decenber 15, 1991 // // Copyright (c) 1992, by Kevin Michael Elbury // ^ main() C // start with a clean structure New(); print("Cross Link Demo Program - (demo.bob)"); // set up the grid and limits SetGrid(1000,1000,0,0,TRUE,TRUE); SetLimits(-1000,-1000,15000,12000); // perfom the demostration Circle(3000.,5000.,3000.,20); SineWave(8000,5000,14000,5000,2000); // update the display Repaint(); // Circle() // %% Creates a circle out of node and elements with origin at x,y // Circle(x,y,radius,points; i,num1,num2,elnum,dx,dy,dt,theta,start) C start = num1 = NodeHigh();^// rememeber the first node num2 = 0; i=1; theta = dt = 2.0 * PI / points; NodePut(num1,x+radius,y,ID_000); while(i<points)f theta = dt * i; dx = x + radius * cos(theta); dy = y + 1.30 * radius * sin(theta); I++; num2 = NodeHigh(); NodePut(num2,dx,dy,ID_000); // get the next element number elnum = ElementHigh(); ElementPut(elnum,num1,num2,ID_FF); num1 = num2; ) // add the element ElementPut(ElementHigh(),num2,start,ID_FF); Repaint(); -114- Cross Link^ Programmer's Reference // SineWave() // X% Creates a sine wave out of node and elements with origin at xo,y0 //^and ending at xf,yf. Amplitude of wave is A. //SineWave(xo,yo,xf,yf,A;num1,num2,spc,w,i,di,dx,dy) num1 = num2 = 0; di = 80; spc = (xf - xo)/ di; w = 12 * PI / (xf-xo); num1 = NodeHigh(); NodePut(numl,xo,yo,ID_000); i = 1; dx = xo; while(dx < xf)( dx = xo + i * spc; dy = yo + A * sin(w * i * spc);I++; num2 = NodeHigh(); NodePut(num2,dx,dy,ID_000); elnum = EtementHigh(); ElementPut(elnum,num1,num2,ID_FF); num1 = num2; ) -115- Cross Link^ Programmer's Reference 3.2 ANSYS File Transfers ANS-IN.BOB The following program provides limited file compatability with the ANSYS finite element program. // ^ // File:^ANS-IN.BOB // Description:^Imports an ANSYS script file into Cross Link // Written By:^KME // Date:^January 14, 1992 // // Copyright (c) 1992, by Kevin Michael Elbury // ^ main(; filename,line,tok,dx,dy) f // set this to the ANSYS file you wish to import filename = "test.dat"; delimit = ","; // field delimiter is a comma - global var file = fopen(filename,"r"); // read in first line and get the first token in the string... line = fread(file); tok = token(line,delimit); max_x = max_y = 3.4 * pow10(-38.0);^// smallest floating point number possible min_x = min_y = 3.4 * pow10(38.0);^// Largest ... // compare first token while(line)C if(strcmp(tok,"N") == 0) readNode(); else if(stromp(tok,"E") == 0) readElement(); else if(strcmp(tok,"0") == 0) readBoundaryCond(); else print("Ignoring command: ",tok); // read and tokenize next line line = fread(file); if(line) tok = token(line,delimit); ); // add 30% margin to limits dx = max_x - min_x; dy = max_y - min_y; dx *= 0.30; dy *= 0.30; minx -= dx; max_x += dx; min_y -= dy; max_y += dy; SetLimits(min_x,min_y,max_x,max_y); Repaint(); // readNode() // %% continues parsing the ANSYS 'N'ode command and adds the node //^to the node database // // Format: //^N,node_num,x_coord,y_coord // -116- Cross Link^ Programmer's Reference readNode( ;num,x,y) C // get the next token string and convert it to a number nun = val(token(0,delimit)); x = val(token(0,delimit)); y = val(token(0,delimit)); // add the node to the data base NodePut(num,x,y,ID_000); // evaluate structure limits max_x = (x > max_x ? x : max_x); max_y = (y > max_y ? y : max_y); min_x = (x < min_x ? x : min_x); min_y = (y < min_y ? y : min_y); // readElement() // %% continues parsing the ANSYS 'E'Lement command //// Format: //^E,lonode_num,hinode_num // readElement( ;Ionode,hinode,num) C // get the next token string and convert it to a number lonode = val(token(0,delimit)); hinode = val(token(0,delimit)); num = ElementHigh(); // add the node to the data base ElementPut(num,lonode,hinode,ID_FF); // readBoundaryCond() // %% Parses the ANSYS 'D'isplacement command . //^and sets the degrees of freedom on the associated nodes // // Format: //^D,node_num,UX,disp(„„UY,ROTZ]// readBoundaryCond(;num,disp,dof,tok) C // get the next token string and convert it to a number nun = val(token(0,delimit)); tok = token(0,delimit); if(strcmp(tok,"UX") == 0) dof = ID_100; else if(strcmp(tok,"UY") == 0) dof = ID_010; else if(stromp(tok,"ROTZ") == 0) dof = ID_001; else print("Error: No support for dof - ",tok," on node ",nun); disp = val(token(0,delimit)); if(disp > 0.0) print("Warning: Displacment > 0 on node ",num); // read in the rest of the degrees of freedom tok = token(0,delimit); while(tok)( if(strcmp(tok,"UX") == 0) dof = dof 1 ID_100;^/ bitwise . OR to add additional dof else if(strcmp(tok,"UY") == 0) dof = dof 1 ID_010; -117- Cross Link^ Programmer's Reference else if(strcmp(tok,"ROTZ") == 0)dof^dof I ID 001; else print("Error: No support for dof - ",tok," on node ",num); tok = token(0,delimit); // add the node to the data base NodeSetD0F(num,dof); Cross Link^ Programmer's Reference ANS-OUT.BOB // ^ // File:^ANS-OUT.BOB // Description:^Exports a Cross Link structure to ANSYS // Written By:^KME // Date:^January 14, 1992 // // Copyright (c) 1992, by Kevin Michael Elbury // ^ main(;file) C file = fopen("test.dat","w"); // write a file header, go directly to PREP? fwrite(file,"! ^ \n"); fwrite(file,"! - Cross Link to ANSYS Transfer -\n"); fwrite(file,"!  \n"); fwrite(file,"/PREP7\n"); fwrite(file,"/TITLE Cross Link to ANSYS Transfer\n"); // dump the data to 'file' writeNodes(file); writeElements(file); writeBoundaryCond(file); // close the file fclose(file); Speaker(); ) // writeNodes() // X% Extracts all node info from the database and dump to file in ANSYS format // // Format: //^N,node_num,x_coord,y_coord writeNodes(file;num,x,y) C print("Writing nodes..."); fwrite(file,"! ^ \n"); fwrite(file,"! ***Node Data\n"); fwrite(file,"! \n"); nun = NodeFirst(); while(num)C x = NodeGetX(num); y = NodeGetY(nun); fwrite(file,"N,",num,",",x,",",y,"\n"); nun = NodeNext(); // writeElements() // X% Extracts all element info from the database and dump to file in ANSYS format // // Format: //^EFlonode_nuv,hinode_nun // writeElements(file;num,lo,hi) C print("Writing elements..."); fwrite(file,"! ^ \n"); fwrite(file,"! ***Element Data\n"); fwrite(file,"!  \n"); nun = ElementFirst(); -119- Cross Link^ Programmer's Reference while(num)( lo = ElementGetLoNode(num); hi = ElementGetHiNode(num); fwrite(file,"E,u,lo,li,u,hi,"\n"); num = ElementNext(); // readBoundaryCond() // %X Scans node database and extracts any boundary conditions in ANSYS format// // Format: //^D,node_num,UX,disp(„„UY,ROTZ1 - (] optional //writeBoundaryCond(file;num,dof) C print("Writing BC's..."); fwrite(file,"! ^ \nu); fwrite(file,"! ***Boundary Conditions \n"); fwrite(file,"! \nu); num = NodeFirst(); while(num)( dof = NodeGetD0F(num); if(dof == ID_100) fwrite(file,"D,u,num,H,UX,0.0\n"); if(dof == 1D_110) fwrite(file,"0,",num,u,UX,0.0,„,UY\n"); else if(dof == 1D_111) fwrite(file,"D,",num,",UX,0.0„„UY,ROTZ\n"); else if(dof == ID_101) fwrite(file,flD,",num,u,UX,O.0„„ROTZ\n"); else if(dof == 1D_001) fwrite(file,"0,",num,",ROTZ,0.0\n"); else if(dof == 10_010) fwrite(file,"D,",num,",UY,0.0\n"); else if(dof == 1D_011) fwrite(file f uD,u,num,H,UY,0.0,„,ROTZ\n"); num = NodeNext(); -120-


Citation Scheme:


Usage Statistics

Country Views Downloads
Canada 7 0
China 5 0
Japan 1 0
City Views Downloads
Surrey 6 0
Beijing 5 0
Victoria 1 0
Tokyo 1 0

{[{ mDataHeader[type] }]} {[{ month[type] }]} {[{ tData[type] }]}


Share to:


Related Items