5. baspl++ Objects

In baspl++, the post-processing tasks (such as database access, computation, rendering, annotation etc.) are handled by different objects, the baspl++ objects. This section gives an overview of the different types ("classes") of baspl++ objects and then describes what defines baspl++ objects and how they are connected to the graphical user interface and to the Python environment.

5.1. Overview of baspl++ Objects

This section gives a brief overview of the different baspl++ objects.

5.1.1. Objects for Mesh and Solution extraction

  • Model: Contains a mesh.

  • Field: Contains values from a solution field.

  • NPart: Extracts or cuts elements from the Model object and interpolates solution fields from Field objects. Rendering for display of extracted meshes and interpolated solution fields.

  • Tracer: Computes 3D particle traces from the Model object and velocity solution field(s) and renders them for display.

5.1.2. Objects for XY-Plotting

  • Curve: A container for x/y-values.

  • Graph: Contains a set of Curve objects and renders them for display.

5.1.3. Objects for OpenGL Display

  • Scene: Displays 2D and 3D objects such as Part, Graph, Tracer objects etc. objects in a "Scene" window using OpenGL. When starting up normally, the global variable s references the default Scene object.

  • LightSource: Light source, needed for OpenGL-lighting. When starting up normally, the global variable l references the default LightSource object.

  • ColourMap: Maps scalar values to colours, needed by NPart objects. By default, the ColourMap objects are created and managed by the NPart objects.

  • VideoRecorder: Creates a movie file from the contents displayed in a Scene window.

5.1.4. Objects for Specific Tasks

  • Modes: Applies solution fields from modal analysis to a NPart object.

  • CFDSurfaceIntegrator: Integrates solution fields over the extracted wall on a NPart object (CFD).

  • CFDXYPlot: Creates CFD-specific XY-plots for one or several databases. Section XY-plots, Line XY-plots, and integral XY-plots.

5.1.5. B2000++ specific Objects

  • HistoryXYPlot: Make an XY-plot of the total reaction forces, a degree-of-freedom, the load factor, a distance criterion, etc. This class is intended for use with B2000++ nonlinear analysis.

  • ViewEBC: Extracts and renders essential boundary conditions as defined by EBC datasets. Only works with the Python interface (type help(ViewEBC)).

  • ViewNBC: Extracts and renders natural boundary conditions as defined by NBC datasets. Only works with the Python interface (type help(ViewNBC)).

  • ViewLINC: Extracts and renders linear constraints. Only works with the Python interface (type help(ViewLINC)).

  • ViewEPATCH: Views EPATCH objects. Only works with the Python interface (type help(ViewEPATCH)).

5.1.6. Objects for Decoration and Annotation

  • Text: Renders a single- or multi-line text.

  • Line: Renders a line in 2D coordinates.

5.1.7. Legacy Objects

  • Part: Old version of NPart.

5.2. Common Features of baspl++ Objects

All baspl++ objects have the following in common:

  • They have an object identifier (a character string) that must be unique. These identifiers are displayed in the tree widget in the main window. The purpose of these identifiers is to help the user to distinguish between objects when working with the graphical user interface. They can also be used to obtain a Python reference to an object that as been created by means of the graphical user interface (see Section 5.5). How to change the identifier is described in Section 5.4.

  • They can be created, manipulated, and deleted by means of the graphical user interface, see Section 5.3.

  • They are Python objects; this means that they can be created, manipulated, and deleted from the Python console and in Python scripts.

    [Note] Note

    Since Python is an object-oriented programming language, the term "object" means "instance" of a "class". For example, a Scene object is an instance of the class "Scene". More information about terminology and an introduction to the Python class mechanism can be found here.

  • In post-processing, the processed data can be very large and the operations performed on this data may be quite complex. Here, the Python programming language, being user-friendly, dynamic, and of interpreted nature, cannot offer the required performance. This gap is filled by the C++ programming language which has become a de-facto standard for performance-hungry, "number-crunching" applications. In baspl++, C++ is combined with Python as follows: For each Python object which performs considerable processing, there is a corresponding C++ object, which is managed by the Python object, remaining hidden from the user. The C++ object does the actual work, while the Python object acts as a proxy: it passes information to and from the C++ object.

    With this mechanism, optimum performance is achieved, and the user does not need to know anything about C++, as the baspl++ object is controlled via the graphical user interface and/or via the Python environment. Typical examples for this mechanism are the Model, Field and NPart objects.

One advantage of the object-oriented approach is that multiple objects can be created for each class. This is illustrated with the following example:

  • Assume that two databases, "case1.mc" and "case2.mc", should be compared. These databases contain a solution field on a Finite-Element mesh.

    For each database, a Model object, a Field object, and a NPart object is created. The NPart objects can be displayed either in the same Scene object, or in different Scene objects, according to the user's needs. The NPart objects may use different ColourMap object to map numerical values to colours, or they may use the same ColourMap object; again depending on the needs of the user.

The duality of the baspl++ objects - being accessible in the graphical user interface and from the Python environment at the same time - is illustrated with the following examples:

  • Assume that the Python script "view.py" has been run, and now there is a Model, a Field, and a NPart object. All these objects are now accessible by means of the graphical user interface: The objects (with their identifiers) are displayed in the tree widget in the main window. They can be selected, which activates their editor. In the editor, they can be modified.

  • Assume that the user has created a number of objects by means of the graphical user interface. Now, the user can assign these objects to Python variables (see Section 5.5). From this moment, the objects can be manipulated from the Python environment (console and scripts).

  • Assume that the user has created a number of objects by means of the graphical user interface. Section 6.1 explains how a Python script is automatically created from the existing set of objects.

5.3. Working with Objects in the Graphical User interface

baspl++ objects have two elements that make part of the graphical user interface: a menu and an editor. When a baspl++ object is selected (usually via the tree widget in the main window), two things happen: First, the Object-> sub-menu in the main window is changed according to the selected object. Second, the editor of the object is activated in the editor area of the main window.

In the menu, the following actions are available for all baspl++ objects:

  • Assign to Python variable. See Section 5.5.

  • Set the object identifier. See Section 5.4.

  • Delete the object. The object and all objects that depend on it will be deleted. See Section 5.6.

The object's editor allows to manipulate all settings of the object. In many cases, it displays additional information: For instance, a Field object contains the minimum and maximum values for the different components. These values are displayed in the editor for inspection. The Field editor allows also to browse over the different elements and nodes and to inspect the respective field values.

Most objects are listed in the tree widget in the main window. An object is selected by clicking on it with the left button of the mouse. With the right button of the mouse, the object is not only selected, but the object's menu appears as a context (pop-up) menu as well.

Objects that are displayed in a Scene object can be selected by clicking the right button of the mouse at the location inside the Scene window where the object in question is displayed. A context (pop-up) menu appears which allows to select the object(s).

5.4. Setting the Identifier of an Object

The identifier of a baspl++ object is displayed in the tree widget in the main window. In the Python environment, it can be obtained via the id property. For instance, the identifier of default Scene object (which is referenced by the global variable s) is obtained

>>> print s.id

To change the identifier of an object from the graphical user interface, make sure that the object is selected and then select Object->Set Object ID... from the menu. A dialog appears where the new identifier can be entered.

To change the identifer of an object from the Python environment, assign the id property:

>>> s.id = 'New Identifier'

5.5. Assigning Objects to Python Variables

To make baspl++ objects created with the graphical user interface accessible from the Python environment, they must be referenced by Python variables.

The most straightforward way of achieving this is to select the object in the graphical user interface and then to select File->Assign to Python variable.... A dialog appears where the name of the global variable to be assigned to the object can be entered. If there are already global variables referencing that object, they are displayed in the same dialog. After that, the object is now additionally referenced by that variable.

Alternatively it is possible to retrieve the existing baspl++ objects by means of the find_object and find_objects functions.

Examples:

m = find_object('airfoil.mc')

assigns the (Model) object having the identifier "airfoil.mc" to the variable m. If the object does not exist, the Python value None is assigned instead.

parts = find_objects(NPart)

assigns the current list of all instances of class NPart to the variable parts.

5.6. Deleting baspl++ Objects; The Concept of References

baspl++ objects have to be deleted by means of the delete function. In the graphical user interface, this can be done by first selecting the object and then activating the Object->Delete item in the main menu. In the Python environment, the object must be referenced by a variable (e.g. o). It is deleted by calling the delete function:

>>> o.delete()

The delete function is a special feature of baspl++ objects. Ordinary Python objects are deleted as soon as they are not referenced anymore. But baspl++ objects are always referenced by the application itself; this is necessary for the proper functioning of the graphical user interface (the tree widget, the menus, the editor area, etc.). By calling the delete function, baspl++ is told that all references to this object should be removed. Another purpose of the delete function is to free all internal memory structures. Thus, after calling the delete function, the object cannot be used anymore.

[Note] Note

This behaviour is in contrast to ordinary Python objects, where the freeing of internal data structures takes place in the object's destructor function. The destructor function is not called by any application code directly, rather it is called either when the object's reference count becomes zero, or when the object is "collected" by Python's automatic garbage collector.

In the remainder of this section, the concept of references is briefly explained.

The concept of references is used by many programming languages, such as Java and Python. What is a reference? In Python, all objects are accessed by reference. That is, the variables are not the objects themselves, instead a variable points to, or better, refers to the object (hence reference). This way, there may be many variables referring to the same object (this is also known as "aliasing").

Example:

>>> a = [1, 2]   # create a list object [1, 2] and reference it by 'a'
>>> print a
[1, 2]
>>> b = a        # create a new reference to the same list object
>>> a.append(3)  # modify the list object by appending the number 3
>>> print b      # 'b' references the same list object
[1, 2, 3]
>>> del a        # delete the reference 'a' (not the list object)
>>> print b      # 'b' is still valid
[1, 2, 3]

Objects remain as long as they are referenced. In the example above, the list object remains because it is still referenced by b. If you issue

del b

no reference to the list object remains and its destructor function is called (in case of cyclic references, these will evenutally be detected by Python's automatic garbage collector, and the destructor function is called during a collection run).