Boundary Conditions programing in Kratos
When we are analyzing a structural problem using Shell element, simple Boundary Conditions can be imposed during Pre Process. An example can be found here: Shell Analysis using Structural Mechanics Application. Sometimes, more complex Boundary Conditions are necessary to properly reproduce the reality. In this case we need to program that in Kratos. This tutorial shows two example where BC have been imposed programming in Kratos with Python.
We use the case proposed here: Shell Analysis using Structural Mechanics Application. It consist in a short beam simply supported in the middle and with two boundaries. Its geometry is shown bellow:
When we run the calcultion from GiD (Calculate > Calculate or F5) some files are added into project folder. One of these is the MainKratos.py file of Python. MainKratos.py is the script of Kratos that includes all the instructions to import applications, read the model and solve it. We must program inside this MainKratos.py script the code to impose BC.
We can add our code in some part after adding the DoF (Degree of Freedom):
And before initializing the solver:
We will write a code to impose displacements and rotations on both boundaries (left_boundary and right_boundary).
Boundary displacement can be imposed through a funtion that iterate over the nodes of that boundary. At each iteration we set de value of DISPLACEMENT_Z of a node.
def ApplyBoundaryDisplacement(left_displacement, right_displacement): #Iterating over nodes for node in main_model_part.GetSubModelPart("DISPLACEMENT_BC_Dirichlet_left_boundary").Nodes: #Setting DISPLACEMENT_Z node.SetSolutionStepValue(DISPLACEMENT_Z, 0, left_displacement) for node in main_model_part.GetSubModelPart("DISPLACEMENT_BC_Dirichlet_right_boundary").Nodes: node.SetSolutionStepValue(DISPLACEMENT_Z, 0, right_displacement) print("--Boundary displacement imposed") return
With main_model_part.GetSubModelPart("DISPLACEMENT_BC_Dirichlet_left_boundary").Nodes we get a vector that contains all the nodes of the SubModelPart DISPLACEMENT_BC_Dirichlet_left_boundary.
With node.SetSolutionStepValue(DISPLACEMENT_Z, 0, left_displacement) we set the value of DISPLACEMENT_Z of that node to the value left_displacement for the current step (because second argument is equal to 0).
DISPLACEMENT_Z degree of freedom must be fixed for nodes in boundaries. Otherwhise, Kratos will not use the imposed values for computing and solving the problem. We can set the DoF of a node as Fixed during Pre Process or programming in Kratos.
The rotation of a section can not be imposed directly to all the section, it must be imposed node by node as a displacement. According theory of strength of materials and structures, points contained in the same plane before beam deformation are contained in the same plane after its deformation. So the section rotates about a certain center of rotation and nodes undergo an horizontal displacement equal to the value of the rotation multiplied by the radius vector of the center of rotation to the node.
node_displacement_x = rotation*(rotation_center.Z - node.Z)
This way the displacement of all nodes is compatible and the nodes are always contained in the same plane.
To carry out this, we need a function to compute the center of rotation of a set of nodes:
def ComputeGeometricCenter(node_list): #Center of rotation X_coordinate_sum = 0 Y_coordinate_sum = 0 Z_coordinate_sum = 0 for node in node_list: X_coordinate_sum += node.X Y_coordinate_sum += node.Y Z_coordinate_sum += node.Z X_coordinate = X_coordinate_sum/len(node_list) Y_coordinate = Y_coordinate_sum/len(node_list) Z_coordinate = Z_coordinate_sum/len(node_list) class center: X = X_coordinate Y = Y_coordinate Z = Z_coordinate return center
Creating a class for center we are consistent with the idea of nodes and we obtain its coordinates in the same way.
Then we can create a function for imposing the values of DISPLACEMENT_X following the same scheme for Boundary Displacement: computing the center of rotation, iterating over the nodes, computing for each node its value of DISPLACEMENT_X and setting this value.
def ApplyBoundaryRotation(left_rotation, right_rotation): #Center of rotation left_rotation_center = ComputeGeometricCenter(main_model_part.GetSubModelPart("DISPLACEMENT_BC_Dirichlet_left_boundary").Nodes) right_rotation_center = ComputeGeometricCenter(main_model_part.GetSubModelPart("DISPLACEMENT_BC_Dirichlet_right_boundary").Nodes) #Iterating over node for node in main_model_part.GetSubModelPart("DISPLACEMENT_BC_Dirichlet_left_boundary").Nodes: #Computing the value of DISPLACEMENT_X node_displacement_x = left_rotation*(left_rotation_center.Z - node.Z) #Setting DISPLACEMENT_X node.SetSolutionStepValue(DISPLACEMENT_X, 0, node_displacement_x) for node in main_model_part.GetSubModelPart("DISPLACEMENT_BC_Dirichlet_right_boundary").Nodes: node_displacement_x = right_rotation*(right_rotation_center.Z - node.Z) node.SetSolutionStepValue(DISPLACEMENT_X, 0, node_displacement_x) print("--Boundary rotation imposed") return
Defining the functions ApplyBoundaryDisplacement and ApplyBoundaryRotation as above, we only need to introduce the values of BC (displacements and rotation) and call the functions.
left_boundary_displacement = -0.002 #[m] right_boundary_displacement = -0.002 #[m] left_boundary_rotation = 0.0009 #[rad] right_boundary_rotation = -0.0009 #[rad]
ApplyBoundaryDisplacement(left_boundary_displacement, right_boundary_displacement) ApplyBoundaryRotation(left_boundary_rotation, right_boundary_rotation)