2. Basics

In this section, we provide a few basic examples of how to use the most simple classes and functions in PyMpc.

2.1. Utilities

The Utils sub-module provides two useful functions to query the directory of the STKO application and the OpenSees external solvers. Here’s an example of how to use them:

from PyMpc import *
d = Utils.get_app_dir()
print(d)
s = Utils.get_external_solvers_dir()
print(s)

Most likely the following will appear in the Terminal.

C:/Program Files/STKO
C:/Program Files/STKO/external_solvers

2.2. Input/Output

The IO sub-module provides three functions to color-code the output text in the terminal. Here’s an example of how to use them:

from PyMpc import *
IO.write_cout("This is an output")
IO.write_clog("This is an log")
IO.write_cerr("This is an error")

Specifically write_cerr can be used to raise exceptions in try loops and allow for better readability of the output. For example:

from PyMpc import *
try:
    print(x)
except Exception:
    IO.write_cerr("Exception: variable x is not defined")

2.3. Units

The Units sub-module provides classes and methods to interact with the unit system. Here’s an example of how to use them:

from PyMpc import *
import PyMpc.Units as u

App.clearTerminal()

L = u.L         #base unit length [meter]
t = u.t         #base unit time [second]
T = u.T         #base unit temperature [Celsius]
r = u.Angle     #derived unit angle [radian]
F = u.F         #derived unit force [Newton]
P = F/(L**2)    #unit pressure [Pascal]
print ("The reference unit of pressure (Pascal):")
print (P)

Note

clearTerminal() is a function of the sub-module App used to clear the terminal from previous printed output.

This is the output you’ll obtain in the Terminal.

The reference unit of pressure (Pascal):
             Dimension:                         F/L^2
         Current units:              1          N/m^2
        Internal units:              1          N/m^2

2.4. Math

The Math sub-module provides vector and matrix objects, available for 2, 3, 4, and n dimensions. Here’s an example of how to use them:

import PyMpc.Math as m

2.5. Fx

Note

The classes referring to the graphic representation for OpenGL still need to be documented.

2.6. Open Cascade

In PyMpc, there are a set of functions and classes to interact wit the CAD environment and directly query geometries, build new elements and interact with existing ones. To separate these set of classes and functions from the rest, three separate sub-modules have been developed: FxoccShape, FxoccQuery, FxoccShape. Where “occ” stands for Open Cascade and “Fx” for graphic representation for OpenGl.

2.6.1. FxoccShape

In the sub-module FxoccShape, there are utilities used to generate Open Cascade data for CAD, in terms of shapes, curves and surfaces.

2.6.2. FxoccBuilder

The sub-module FxoccBuilder includes functions to create vertices, edges and faces and creating from them wires, compounds and shells. An example on how to use this sub-module will be provided in section Geometries.

2.6.3. FxoccQuery

In the sub-module FxoccQuery the class DistanceInfo and method computeDistance can be used to query information on the distance of two FxOccShape instances. The following example will illustrate how to create new geometric elements in the Preprocessor environment and successively query information about their respective position.

First let’s initialize our script and call the MpcCaeDocument class and assign it to the variable doc.

from PyMpc import *

App.clearTerminal()
doc = App.caeDocument()

All geometries created need to be indexed. To ensure consistency between existing indices and new ones follow these steps (further explanation is provided in section Geometries)

id = 0
if len(doc.geometries) > 0:
    id = doc.geometries.keys()[-1]
print(id)

def get_id():
    global id
    id += 1
    return id

Let’s create two edges, a vertical one and an horizontal one.

v1 = FxOccBuilder.makeVertex(0,0,0)
v2 = FxOccBuilder.makeVertex(100, 0, 0)
e1 = FxOccBuilder.makeEdge(v1,v2)

v3 = FxOccBuilder.makeVertex(50,100,0)
v4 = FxOccBuilder.makeVertex(50,-100, 0)
e2 = FxOccBuilder.makeEdge(v3,v4)
add_geom(MpcGeometry(get_id(), "Shape1", e1))
add_geom(MpcGeometry(get_id(), "Shape2", e2))

Finally, compute the distance between two shapes and then query information on it. The distance will be 0.0, and the parameters p1 and p2 will coincide in each solution, given that there is an intersection between the two shapes.

info = FxOccQuery.computeDistance(e1, e2)
print('Done:', info.done)
print('Inside:', info.inside)
print('Distance:', info.minimumDistance)
print('Number of solutions', info.numberOfSolutions)
for i in range(info.numberOfSolutions):
    print("Info p1[{}]:".format(i),info.p1[i])
    print("Info p2[{}]:".format(i),info.p2[i])

The following will appear in the terminal.

Done: True
Inside: False
Distance: 0.0
Number of solutions: 2
Info p1[0]: [0;0;0]
Info p2[0]: [0;0;0]
Info p1[1]: [100;0;0]
Info p2[1]: [100;0;0]

2.7. Qt

STKO uses Qt for its GUI and offers its use to the user through the PySide2 package. Here’s an example of how to create a simple GUI with a button and a label:

from PyMpc import *
from PySide2 import QtWidgets, QtCore
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QPushButton, QLabel, QVBoxLayout, QWizardPage

class MyMainWindow(QtWidgets.QMainWindow):
    def __init__(self):
            super().__init__()
            self.setWindowTitle("")
            self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)

            page1 = MyPage(self)
            self.setCentralWidget(page1)

class MyPage(QWizardPage):
    def __init__(self, parent=None):
            super().__init__(parent)
            self.setWindowTitle("")
            self.setGeometry(300, 300, 400, 300)

            self.layout = QVBoxLayout()

            self.label = QLabel('Print "Hello World!"')

            self.button = QPushButton("Click me!")
            self.button.clicked.connect(self.onButtonClicked)

            self.layout.addWidget(self.label)
            self.layout.addWidget(self.button)
            self.setLayout(self.layout)

    def onButtonClicked(self):
        App.clearTerminal()
            IO.write_cout("Hello World!\n")

if __name__ == "__main__":
    mainWindow = MyMainWindow()
    mainWindow.show()

For further instructions about on how to use the PySide2 package, please refer to the PySide2 documentation.

2.8. Chart

The MpcChart sub-module provides classes to create new charts and chart data. Here’s an example of how to use them:

from PyMpc import *
import numpy as np
from time import sleep

doc = App.postDocument()

doc.clearCharts()
doc.clearChartData()
doc.commitChanges()
doc.dirty = True

To illustrate the creation in turn of new chart data sets, new chart data items to input in the charts and finally new charts, a for loop of 10 iterations has been set as follows. In the first block of code inside the loop a new MpcChartData instance is created, and several attributes are assigned to it: an id, a name, and labels for the x and y axis. Random values are assigned to x and y in this example, but the user could choose to call an data from the .spd file or even call data saved externally. For example, with this method it will be possible to operate comparisons directly inside STKO with experimental data.

for iter in range(10):
    cdata = MpcChartData()
    cdata.id = doc.genNextIdForChartData()
    cdata.name = "Test Chart Data %i" % iter
    cdata.xLabel = "XData"
    cdata.yLabel = "YData"
    x = np.linspace(0.0, 4.0*float(iter), 1000)
    y = np.sin(x) * np.logspace(1.0, 1.0+float(iter)/10.0, 1000)
    cdata.x = Math.double_array(x.tolist())
    cdata.y = Math.double_array(y.tolist())
    doc.addChartData(cdata)
    doc.commitChanges()
    doc.dirty = True
    doc.select(cdata)
    App.processEvents()
    sleep(0.2)

After, always writing inside the for loop, an MpcChartDataGraphicItem for cdata is instantiated. It is necessary to create an instance of this class in order to visualize the chart data in the chart. Attributes such as color, thickness and penStyle of the item can be assigned.

cdata_item = MpcChartDataGraphicItem(cdata)
cdata_item.color = MpcQColor(255, 150, 0, 255)
cdata_item.thickness = 1.5
cdata_item.penStyle = MpcQPenStyle.SolidLine
Finally the chart is created and the chart data set is added to it

chart = MpcChart()
chart.id = doc.genNextIdForChart()
chart.name = "Test Chart"
chart.addItem(cdata_item)
doc.addChart(chart)
doc.commitChanges()
doc.dirty = True
doc.select(chart)
App.processEvents()
sleep(0.2)