Getting started
Python is an interpreted, interactive object-oriented programming language sometimes compared to Perl, Java, and Tcl. It has interfaces to IP networking, windowing systems, audio, and other technologies. Integrated with CivilFEM, it provides a more powerful scripting language than procedure files as it contains conditional logic and looping statements such as if, while, and for.
Data Types
When programming in Python, you don’t explicitly declare a variable’s data type. Python determines this characteristics by how the variable is being used. Python supports the following implied data types:
numbers: A floating point number similar to double data type in C and the real8 data type in Fortran, or an integer or fixed point number similar to the long int data type in C and the integer8 data type in Fortran:
# Beware of type conversions between integer and float
int(2.3) # 2
int(-2.8) # -2
float(5) # 5.0
# Take care when comparing floats due to precision errors of machine representation
(1.1 + 2.2) == 3.3 # ! False
1.1 + 2.2 # 3.3000000000000003
When precision matters, use “Decimal” standard library:
from decimal import Decimal as D
print(D('1.1') + D('2.2')) # 3.3
print(D('1.2') * D('2.50')) # 3.000
Sometimes this precision error is propagated when doing multiple math operations. To avoid this, it is convenient to have partial values in fractions:
from fractions import Fraction as F
print(F(1, 3) + F(1, 3)) # 2/3
print(1 / F(5, 6)) # 6/5
print(F(-3, 10) > 0) # False
print(F(-3, 10) < 0) # True
string: A character string similar to char data in C and character in Fortran. A string may be specified using either single or double quotes.
# defining strings in Python
# all of the following are equivalent
my_Geom_Name = 'Top Surface'
print(my_Geom_Name)
my_Geom_Name = "Bottom Surface"
print(my_Geom_Name)
my_Geom_Name = '''Middle Surface'''
print(my_Geom_Name)
# triple quotes string can extend multiple lines
my_String = """Hello, welcome to
the world of Python"""
print(my_String)
Some special caracters combinations may break the string. For example \n: new line, or \t: add a tabulation. The backslash is used to input this codes. One way to skip it is using “Raw” strings, so “escape” sequences are ignored:
print("C:\\Python32\\Lib") # C:\Python32\Lib
# Raw strings are preceded by "r"
print(r"C:\Python32\Lib") # C:\Python32\Lib
When you need membership operations you can do it as follows:
'a' in 'program' # True
'at' not in 'battle' # False
To concatenate strings:
# Python String Operations
str1 = 'Curve_'
str2 ='Top_'
number = 1
# using +
str1 + str2 # 'Curve_Top_'
# using str() function to convert types to a string representation
str1 + str2 + str(number) # 'Curve_Top_1'
list: A Python list is essentially a linked list that can be accessed like an array using the square bracket operators [ ]. The list can be composed of strings, floats, or integers to name a few:
# List of integers
my_list = [1, 2, 3]
# Empty list
my_list = []
# List with mixed data types
my_list = [1, "myBeam", 3.4]
# List indexing
my_list = ['p', 'r', 'o', 'b', 'e']
print(my_list[0]) # p
print(my_list[2]) # o
print(my_list[4]) # e
# Nested List
n_list = ["Happy", [2, 0, 1, 5]]
# Nested indexing
print(n_list[0][1])
print(n_list[1][3])
# Error! Only integer can be used for indexing
print(my_list[4.0])
# Negative indexing
my_list = ['p','r','o','b','e']
print(my_list[-1])
print(my_list[-5])
dict: A Python dictionary is an associative container like map in which a key variable is asociated with a value variable. Its elements are accessed with braces:
# Empty dictionary
my_dict = {}
# Dictionary with integer keys
my_dict = {1: 'myShell', 2: 'mySolid'}
# Dictionary with mixed keys
my_dict = {'myGeom': 'myShell', 1: [2, 4, 3]}
# Using dict()
my_dict = dict({1:'myCurve', 2:'mySurface'})
# From sequence having each item as a pair
my_dict = dict([(1,'myCurve'), (2,'mySurface')])
Python offers modules like math to carry out different mathematics like trigonometry, logarithms, probability and statistics, etc:
import math
print(math.pi)
print(math.cos(math.pi))
print(math.exp(10))
print(math.log10(1000))
print(math.sinh(1))
print(math.factorial(6))
Syntax
There are some syntax considerations to keep in mind when programming in Python.
Names and default arguments are designated between quotation marks (ex: “name”).
Python is a case sensitive language, recognizing capital and small letters as different variables.
To create loops using for, if, while, lines of Python code that define the function must be indented at least one space. To end the function definition, the code is “unindented”.
Python have some reserved words that cannot be used to name variables: and, assert, break, class, continue, def, del, elif, else, except, exec, finally, for, from, global, if, import, in, is, lambda, not, or, pass, print, raise, return, try, while, yield.
As Python reserved words, CivilFEM commands and classes names cannot be used to name variables, or you can expect odd behaviours:
createPoint([1,2,3]) # Ok, create a geometry point
createPoint = 1 # name value change from a CivilFEM command to 1 integer
createPoint([1,2,3]) # !Error, createPoint was modified to an integer, is not a function any more
Loops
As previously mentioned all Python functions are enabled in CivilFEM. When the range function is used, Python builds a list of integers starting at the first value and ending at one less than the last value. For example:
for i in range(0,5):
print(str(i) + "*" + str(i) + "=" + i ** 2)
is actually executed as:
for i in [0,1,2,3,4]:
print(str(i) + "*" + str(i) + "=" + i ** 2)
You can set the step (by default is 1) with the third argument:
for i in range(0,5,2):
print(str(i) + "*" + str(i) + "=" + i ** 2)
equivalent to:
for i in [0,2,4]:
print(str(i) + "*" + str(i) + "=" + i ** 2)
Range works with integer values for the iterator. If you want an iterator with float values, you need to use a while loop:
i = 0.0 # 0.0 (float) instead of 0 (integer)
while (i < 5.0):
print(str(i) + "*" + str(i) + "=" + i ** 2)
i += 0.75
Break and Continue statements in a loop are helpful options when you need to stop or ignore part of the loop:
for i in range(0,5):
if i == 3:
break # stops when the statement is executed and exits the loop
print(i)
for i in range(0,5):
if i == 3:
continue # the iteration 3 is ignored and continue with the next one
print(i)
Functions
Sometimes it can be useful to use functions to reuse code, that is, to avoid repetition, and to write clearer and more understandable code. For example, consider the following code:
# Function definition to check if the result is ok
def CheckPostensionResult(load, tension, time, expectedResult):
load.PrestressType = "Stress"
load.Tendons[0].StressValue = Double(tension, "MPa")
calculateLosses([load],Double(0.9),Double(0),Double(time, "hAge"))
load.PrestressType = "Force"
result = load.Tendons[0].PrestLossesForce.get(0, 5)
logStr = "[Tension] " + str(tension) + " MPa" \
+ " [Time] " + str(time) + " h" \
+ " [Expected] " + str(expectedResult) + " kN" \
+ " [Obtained] " + str(result) + " kN"
if not math.isclose(expectedResult, result, rel_tol=0.01): # tolerance 1%
LogError("Invalid Result -> " + logStr)
# Main execution starts here!
# Test data
tensionsMPa = [ 1328.0, 1328.0, 1328.0, 885.0, 973.5, 973.5, 973.5 ]
timeHours = [ 1000.0, 800000.0, 20.0, 1000.0, 1000.0, 500.0, 1000000.0]
resultsKN = [ 79.68, 207.17, 27.89, 0.0, 7.301, 6.206, 21.903 ]
# Check each result with our custom function
numTests = len(tensionsMPa)
for i in range(numTests):
CheckPostensionResult(tensionLoad, tensionsMPa[i], timeHours[i], resultsKN[i])
Utilities
Python is able to run scripts already created using the command execfile, only by giving the path of the file:
exec(open(r"C:\CivilFem\script\example.py").read())
Note
All available Python libraries and its uses can be found at the following: https://docs.python.org/3/library/