# 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 real*8 data type in Fortran, or an integer or fixed point number similar to the long int data type in C and the integer*8 data type in Fortran: ```{code-block} # 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: ```{code-block} 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: ```{code-block} 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. ```{code-block} # 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: ```{code-block} 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: ```{code-block} 'a' in 'program' # True 'at' not in 'battle' # False ``` To concatenate strings: ```{code-block} # 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: ```{code-block} # 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: ```{code-block} # 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: ```{code-block} 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: ```{code-block} 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: ```{code-block} for i in range(0,5): print(str(i) + "*" + str(i) + "=" + i ** 2) ``` is actually executed as: ```{code-block} 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: ```{code-block} for i in range(0,5,2): print(str(i) + "*" + str(i) + "=" + i ** 2) ``` equivalent to: ```{code-block} 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: ```{code-block} 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: ```{code-block} 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: ```{code-block} # 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: ```{code-block} exec(open(r"C:\CivilFem\script\example.py").read()) ``` ```{note} All available Python libraries and its uses can be found at the following: ```