Chapter 1Linear Elastic 2D frame

In this example, we will learn how to solve in OpenSEES an elastic frame subjected to a static horizontal load.

1.1 Description of the frame

The proposed example is a frame composed of two columns (1,2) supporting one beam (3) (Figure 1.1.1). Nodes are numbered as 1, 2, 3 and 4 from the bottom-left clock-wise. The two base nodes (1,2) are fully constrained. The height of the frame is L and the span is L2. The material composing the columns and the beams is elastic and characterized by an elastic modulus equal to E. The cross-section is the same for all the beams; it is rectangular with base, B, and height, H. Two horizontal loads equal to F3 and F4 are applied to the nodes 3 and 4, respectively. A right-handed reference system (x,y) is introduced with the x-axis pointing in the horizontal direction and the y-axis pointing vertical. The origin of this reference system is located in the node 1.

In the following, the elastic frame will be solved in OpenSEES.

1.2 OpenSEES implementation

In the following, the code implementation of the solution of the elastic frame will be done according to the following steps:

• Title
• Inputs
• Model
• Recorder
• Analysis
• Screen print

1.2.1 Title

The first step in the implementation of the any code is to write indication about the title (what the code is doing). To add this information to the code, a comment should be used. To define an inline comment in Tcl Use the hashtag, #, should be employed in the beginning of the line. # Comment lines are stripped out before the script is evaluated. To start the title section, the following lines can be used:

# TITLE
# ------------------------------

Here and in the following, this format will be used to define each section of the code.

The title (Frame (Linear and Elastic)) can be inserted as:

# Frame (Linear and Elastic)

The OpenSEES interpreter does not process units. Accordingly, it is important that all the inputs should be expressed in the same unit. In the title section Title, it is important to declare the units employed. In this case, we will use Newton for the forces, millimeters for the distances and seconds for the time.

# Units: N, mm, sec

In general, before to run a code, it is important to remove all previous assignments. The wipe command should be used at the beginning of the input to clear any previous OpenSEES-objects definition in order to start a new type of analysis. In order to achieve this result, one line with a comment explaining the wipe function will be added followed by one line in which the wipe command will be applied:

# Remove existing model:
wipe

The scope of the analysis is to produce some output file. It is convenient to place all output data in a subdirectory. The file mkdir dir? dir? command ensures that the directories named by the dir arguments exist, creating them if necessary and also creating as necessary any pathname components of each dir. To create a subdirectory named “Data” the following lines will be added using the command file mkdir:

# Create data directories:
file mkdir Data

1.2.2 Inputs

In order to start the Inputs section, the following lines can be used:

# INPUTS
# ------------------------------

In the inputs steps, it is important to define all the variables that will be used in the following. In fact, typically, a program consists of instructions that tell the computer what to do and data that the program uses when it is running. It is important to define the variable since this data can then be used throughout the program. On the other hand, if these are not defined at the beginning of the code, their variation imply to change them throughout the code.

The assignment command in Tcl is set. First, the length of the columns, L, and of the beam, L2, should be defined; these will be assigned to be equal to L = 5000mm and L2 = 3000mm as:

# Define the length of the beam and of the column:
set L 5000.
set L2 3000.

Note that the decimal point is added after the number because they must be defined as floating-point values.

Similarly, the base and height of the rectangular cross section can be defined equal to B = H = 50mm as:

# Define cross-section:
set B 50.
set H 50.

The elastic modulus can be defined to be E = 2.1 ´ 105 as:

# Define elastic modulus:
set E 2.1e5

The horizontal forces, F3 and F4, are defined to be equal to 1000N:

# Define horizontal forces:
set F3 1000.
set F4 1000.

Some of the variables are derived from other previously-defined variables. In this case, the elastic modulus, the area and the inertia of the cross-section are defined as the elastic properties of a generice beam. For a rectangular cross-section, the area is the product between the base and the height, B ´H, and the inertia is ´B ´H3. Arithmetic and logical operations (plus some string comparisons) are in Tcl concentrated in the expr command.

It should be highlighted that references to variables have to be done with $var. Accordingly, to calculate the area the following code can be used: expr$B*$H. This code concatenates the three arguments ($B,*,$H), evaluates the result as a Tcl expression (the product between the referred variable$B with $H using the operator *), and returns the value of the result. This expression is inserted in a set expression to assign the result to a variable named A: set A [expr$B*$H]. The square brackets are added to grouping arguments. It is important to use the square brackets to define arguments in the commands. For instance, the code: set A expr$B*$H will give an error (wrong # args: should be "set varName ?newValue?") as the set command accept only two arguments. Similarly, the inertia is calculated and assigned to a variable named I using the following algebraic calculations expr 1./12.*$B*pow($H,3), where pow(arg1,arg2) is the power arg2 assigned to arg1. A and I are assigned and calculated using the following code lines: # Compute area and inertia: set A [expr$B*$H] set I [expr 1./12.*$B*pow($H,3)] 1.2.3 Model In order to start the Model section, the following lines can be used: # MODEL # ------------------------------ 1.2.3.1 ModelBuilder Before to start, the model builder should be create using the OpenSEES model command. Currently, there is only one model builder available, basic model builder, this is the model builder that includes all the commands presented in this library. In particular, this command expands the Tcl command library to include OpenSEES-specific commands, such as allow for the construction of Nodes, Masses, Materials (nDMaterial Command, uniaxialMaterial Command), Sections, Elements, LoadPatterns, TimeSeries, Transformations, Blocks and Constraints. Some of these command will be described in the following. Moreover, model builder also defines the number of dimensions (ndm) and degrees of freedom per node (ndf). The command “model BasicBuilder -ndm$ndm <-ndf $ndf>” create a model builder based on the basic model builder with number of dimensions equal to$ndm and degrees of freedom per node equal to $ndf. The angle brackets, <>, indicates that the argument number of degrees of freedom at node is optional. Default value depends on value of$ndm: $ndm=1®$ndf=1; $ndm=2®$ndf=3; $ndm=3®$ndf=6.

The basic model builder with two-dimensions (being the problem plane, Figure 1.1.1) and three DOF/node is started using the following code lines:

# Create ModelBuilder:
model BasicBuilder -ndm 2 -ndf 3
1.2.3.2 Nodes

The node should be created and then the elements to create the model. The following comment is added to start the part of the code devoted to the definition (in terms of location and boundary conditions) of the nodes:

# Define nodes:

The node location and tag (and mass) are defined using the OpenSEES node command. The command “node $nodeTag (ndm$coords) <-mass (ndf $massValues)>” create a node with integer tag identifying node$nodeTag, location (ndm $coords) in the form xCrd yCrd (for the two-dimensions case) and <-mass (ndf$massValues)> in the form mx, my (for the two-dimensions case). The latter argument is optional and in this example will not be used as this is a static problem and the mass is not involved. Please note that here and in the following, each integer tag identifying, should be unique for each command (e.g., Nodes, Masses, Materials, etc.).

In order to define the location of the node, a reference system should be defined; this is defined in Figure 1.1.1 with the origin located in the node 1. With respect to this reference system the 4 nodes are located at the following coordinates (0,0) for 1, (L2,0) for 2, (0,L) for 3 and (L2,L) for 4. Neglecting the mass since the problem is static, the four nodes are defined using the following code lines:

node 1 0.0 0.0
node 2 $L2 0.0 node 3 0.0$L
node 4 $L2$L

The boundary conditions are defined using the command fix. This command is used to construct single-point homogeneous boundary constraints. The command “fix $nodeTag (ndf$constrValues)” assign to the node $nodeTag the ndf constraint values (0 or 1) corresponding to the ndf degrees-of-freedom in the form xResrnt? yRestrnt? rRestrnt? (for 3 DOF/node) in which the first constraint values refers to the displacements in the x-direction, the second to the displacements in the y-direction and the third to the rotations around the z-axis. The constraint value 0 is unconstrained (or free) and the constraint value 1 is constrained (or fixed). As reported in in Figure 1.1.1, the nodes 1 and 2 are fixed and the nodes 3 and 4 free. The boundary conditions are applied using the following code lines: # Set the boundary conditions: fix 1 1 1 1 fix 2 1 1 1 fix 3 0 0 0 fix 4 0 0 0 Please note that the unconstrained nodes can be omitted from the code since unconstrained in the default definition of each node. Accordingly, the following code will produce the same results. 1.2.3.4 Geometric transformation and elements The following comment is added to start the part of the code devoted to the definition of the elements: # Define geometric transformation and elements: The way in which the element coordinates correlate to the global model coordinates is defined using the OpenSEES Geometric Transformation command. In particular, the Geometric Transformation command defines how the solver transforms the stiffness and resisting forces of the beam element from the basic system to the global-coordinate system. The command “geomTransf transfType? arg1? ...” assign the geometric transformation type transfType? with its arguments arg1? ... to the geometric transformation rules. In OpenSEES, the following geometric transformation type, transfType?, are available: • Linear Transformation: it performs a linear geometric transformation of stiffness and resisting forces belonging to beam from the basic system to the global-coordinate system; • PDelta Transformation: it performs a linear geometric transformation of stiffness and resisting force belonging to beam from the basic system to the global coordinate system, considering second-order P-Delta effects; • Corotational Transformation: it can be used in large displacement-small strain problems. In this exercise, a linear elastic structure is analyzed. Accordingly, the Linear Transformation will be employed. The command “geomTransf Linear$transfTag <-jntOffset $dXi$dYi $dXj$dYj>” (for a two-dimensional problem) assign the Linear Transformation as geometric transformation with $transfTag integer tag identifying transformation. The optional arguments <-jntOffset$dXi $dYi$dXj $dYj>” specifies rigid joint offsets with the -jntOset switch. The joint offset values dXi, dYi and dXj, dYj are absolute offsets with respect to the global coordinate system from element end nodes I and J, respectively. A Linear Transformation with tag 1 is created using the following code lines: # Define geometric transformation: geomTransf Linear 1 The next step is the definition of the three elements (i.e., beams) connecting the four nodes. The element command is used to construct an Element object. The command has at least one argument, the element type. Different elements are available in OpenSEES. Three elements are mainly available for the definition of an elastic beam element: • Elastic Beam Column Element; • Elastic Beam Column Element with Stiffness Modifiers; • Elastic Timoshenko Beam Column Element. In this exercise, a linear elastic structure is analyzed and accordingly, Elastic Beam Column Elements will be employed. For a two-dimensional problem, the eleTag, the tag of the two end nodes, the section area, the Young’s modulus and the second moment of section area should be defined. In particular, the command “element elasticBeamColumn$eleTag $iNode$jNode $A$E $Iz$transfTag <-mass $massDens> <-cMass>” creates an Elastic Beam Column Element with$eleTag integer tag identifying element between the $iNode and$jNode end nodes. Moreover, the following characteristics should be assigned to this element: $A is the section area,$E is the Young’s modulus, $Iz is the second moment of section area and$transfTag is the previously-defined integer tag identifying transformation (note that different Geometric Transformation can be assigned to different elements). The -mass switch defines the element mass per unit length optional argument that in default is 0.0. Finally, the -cMass switch is to form consistent mass matrix that in default is lumped mass matrix.

In this exercise, three Elastic Beam Column Elements, representing the two columns and the beam, are defined. All these elements will have the same section area, Young’s modulus and second moment of section area. The values of these characteristics of the beam were previously defined in the Input Section with the variable name A, E and I, respectively. Moreover, the Linear Transformation will be assigned to all these elements. The Linear Transformation was previously defined and indicated with the tag 1. As shown in the Figure 1.1.1, the element 1 connects the nodes 1 and 3, the element 2 connects the nodes 2 and 4 and the element 3 connects the nodes 3 and 4 (see Figure 1.1.1). The three Elastic Beam Column Elements are created using the following code lines:

# Create elements:
element elasticBeamColumn 1 1 3 $A$E $I 1 element elasticBeamColumn 2 2 4$A $E$I 1
element elasticBeamColumn 3 3 4 $A$E $I 1 Note that the symbol$ is added in front of the previously-created variables (A, E, I) to recall them. In this example, the integer tag that identifying transformation is not defined in terms of variable but directly using the integer number. This can make difficult a rapidly modification of the code, especially when a large number of elements is defined. In order to define the integer tag identifying transformation in terms of a variable, the last five lines of code can be modified in:

# Define geometric transformation:
set transfTag1 1
# Define geometric transformation:
geomTransf Linear $transfTag1 # Create elements: element elasticBeamColumn 1 1 3$A $E$I $transfTag1 element elasticBeamColumn 2 2 4$A $E$I $transfTag1 element elasticBeamColumn 3 3 4$A $E$I $transfTag1 1.2.4 Loads In order to start the Loads section, the following lines can be used: # LOADS # ------------------------------ 1.2.4.1 Time series Before to define the loads, a TimeSeries object should be defined which represents the relationship between the time in the domain, t, and the load factor applied to the loads, l, in the load pattern with which the TimeSeries object is associated, i.e. l = F(t). It should be highlighted that in OpenSEES the concept of time is the same in the static and dynamic problems. In the static problems, it is related to the step of the analysis. In general, the command “timeSeries seriesType? arg1? ...” creates a time series with time series objects seriesType? with a number of arguments. There are a number of time series objects (seriesType?) that can be constructed: Constant, Linear, Rectangular, Sine, and Series. In this case, the load is linearly increased from zero to the assigned value. This can be expressed in the form: l = F(t) = Cfactor × t. The command “timeSeries Linear$tag <-factor $cFactor>” creates a Linear time series with$tag integer tag identifying timeSeries. The -factor switch is to define the optional argument $cFactor that is the linear factor, Cfactor, that in default is 1.0. A Linear time series with tag 1 without specifying the$cFactor (i.e., by assuming it equal to 1) is created using the following code lines:

# Create TimeSeries object:
timeSeries Linear 1
1.2.4.2 Pattern

• Plain Pattern;
• Uniform Excitation Pattern (this type of pattern imposes a user-defined acceleration record to all fixed nodes, in a specified direction);
• Multi-Support Excitation Pattern (this type of pattern imposes a user-defined displacement record at specified nodes, in a specified direction, or a ground-motion record);

In this exercise, static forces are applied to the structure, and a Plain Pattern will be adopted. Each plain load pattern is associated with a TimeSeries object and can contain multiple ElementalLoads, NodalLoads and SinglePointConstraints objects. The command “pattern Plain $patternTag$tsTag <-fact $cFactor> { load... eleLoad... sp... }” creates a Plain Pattern with$patternTag integer tag identifying pattern and TimeSeries $tsTag. The switch -fact allows for the variation of the$cFactor of the time series that is in default equal to 1.0. All the loads and the single-point constraints in the pattern are contained it the curly brackets. In OpenSEES, two types of loads can be defined namely nodal load and elemental loads (distributed or point). The command “load $nodeTag (ndf$LoadValues)” creates a loads applied to the node with tag $nodeTag. In the node, the reference load values are specified though ndf (DoF/node)$loadvalues. The command “load $eleLoad -ele$eleTag1 <$eleTag2 ....> -type -beamUniform$Wy <$Wx>” applies to the element$eleTag1 (or to the elements $eleTag1$eleTag2 ....) a uniform load with reference magnitude acting in local y direction of element, $Wy, and acting in direction along member length,$Wx. The latter is an optional argument. Similarly, the “load eleLoad -range $eleTag1$eleTag2 -type -beamPoint $Py$xL <$Px>” applies to the element in the range from tag$eleTag1 to $eleTag2 a point load with reference magnitude acting in local y direction of element,$Py, and applied at a fraction of element length relative to the node I, $xL. Moreover, an optional argument giving the reference magnitude of the point load acting in direction along member length can be assigned that in default is equal to 0.0. It should be highlighted that the element loads are only applied to line elements since continuum elements do not accept element loads. The following code lines are used to define the loads applied to the structure: # Create a Plain load pattern with a linear TimeSeries: pattern Plain 1 1 { load 3$F3 0 0
load 4 $F4 0 0 } In particular, these lines of code construct a load pattern with tag 1 and time series tag 1 and populate it with two horizontal forces (in the x- direction) applied to the nodes with tag 3 and 4 of reference magnitude equal to the previously defined variable F3 and F4 (Figure 1.1.1), The zeros in the command load refers to the vertical and moment forces that in this example are set equal to zero. Finally, it should be highlighted that being the Cfactor assumed in the Linear time series equal to 1.0, the final values of the reference magnitude of the loads are equal to the actual one (if t = 1). In order to add a vertical downward distributed load to the beam (element with tag 3) of reference magnitude equal to 100Nmm to the previous loads, the last lines of code can be modified in: # Create a Plain load pattern with a linear TimeSeries: pattern Plain 1 1 { load 3$F3 0 0
load 4 $F4 0 0 eleLoad -ele 3 -type -beamUniform -100 0 } The negative value assigned to the distributed load (i.e. -100) derives from the downward direction that is opposite to the assumed reference system. 1.2.5 Recorder In order to start the Recorder section, the following lines can be used: # RECORDER # ------------------------------ Once the model and analysis objects have been defined, the quantities that should be monitored during the analysis should be specified. Usually, several Recorder objects are created to monitor the analysis with the aim of obtain results and also check the analysis. The command “recorder recorderType? arg1? ...” creates a recorder type recorderType? with a number of arguments. The following recorder types recorderType? are available in OpenSEES: • Node • Node Recorder • Node Envelope Recorder • Drift Recorder • Element/Section/Fiber • Element Recorder • Element Envelope Recorder • Graphics • Plot Recorder In particular, the Node Recorder, the Drift Recorder and the Element Recorder will be analyzed in this example. The Node Envelope Recorder and the Element Envelope Recorder records the min, max and absolute max of a number quantities and will not be used in the following. 1.2.5.1 Node recorder The command “recorder Node <-file$fileName> <-xml $fileName> <-binary$fileName> <-tcp $inetAddress$port> <-precision $nSD> <-timeSeries$tsTag> <-time> <-dT $deltaT> <-closeOnWrite> <-node$node1 $node2 ...> <-nodeRange$startNode $endNode> <-region$regionTag> -dof ($dof1$dof2 ...) $respType’” creates a node recorder with output filename named$fileName in the format: textual (-file option), xml format (-xml option) or binary (-binary option). One of the output should be mandatory defined. The switch:

• -tcp is used to define an optional argument that defines the ip address, $inetAddr, "xx.xx.xx.xx", of the remote machine to which data is sent and the port on remote machine awaiting tcp,$port (for server applications);
• -precision is used to set the optional argument that defines the number of significant digits that in default is 6;
• -timeSeries is used to set the optional argument that defines the the tag of a previously constructed TimeSeries, $tsTag; • -time is used to place the domain time in first entry of each data line (i.e. first column) that in default is omitted; • -dT is used to set the optional argument defining the time interval for recording,$deltaT, that is in default recording at every time step;
• -closeOnWrite is used to instruct the recorder to invoke a close on the data handler after every time-step (a file will be closed on every step and then re-opened for the next step);
• -node, -nodeRange, -region. One of these should be mandatory defined:
1. -node defines the nodes with tag $node1$node2 ... to be recorded;
2. -nodeRange defines the nodes range from tag $startNode to$endNode to be recorded;
3. -region defines the nodes as those belonging to a region defined with tag $regionTag using the command regions; • -dof is used to set the arguments defining DoF with tag$dof1 $dof2 ... whose response is requested; •$respType is an argument defining the response type required. The following response types, $respType, are available in OpenSEES: • disp displacement; • vel velocity; • accel acceleration; • incrDisp incremental displacement; • "eigen i" eigenvector for mode i; • reaction nodal reaction; • rayleighForces damping forces; In this example, the node recorder is used to output displacements of the DoFs from 1 to 3 of the free nodes (nodes 3 and 4, Figure 1.1.1) and support reaction of the DoFs from 1 to 3 of the constrained nodes (nodes 1 and 2) into the textual files DFree.out and RBase.out, respectively. It should be highlighted that the extension .out can be varied. In fact, the output file is a ASCII text file. These files are located in the subfolder Data created in the Section Title (Section 1.2.1). The following code lines are used to create the two node recorders: # Create a Recorder object for the nodal displacements: recorder Node -file Data/DFree.out -time -node 3 4 -dof 1 2 3 disp # Create a Recorder object for the nodal reactions: recorder Node -file Data/RBase.out -time -node 1 2 -dof 1 2 3 reaction The first column of the file D_Free.out is the time, and the last six columns are the displacements of the two free nodes (3 and 4). The first column of the file RBase.out is the time, and the last six columns are the reaction forces of the two fixed nodes (1 and 2). 1.2.5.2 Drift recorder The command “recorder Drift <-file$fileName> <-xml $fileName> <-binary$fileName> <-tcp $inetAddress$port> <-precision $nSD> <-time> -iNode$inode1 $inode2 ... -jNode$jnode1 $jnode2 ... -dof$dof1 $dof2 ... -perpDirn$perpDirn1 $perpDirn2 ...” creates an drift recorder with output filename named$fileName in the format: textual (-file option), xml format (-xml option) or binary (-binary option). One of the output should be mandatory defined. The switch:

• -tcp is used to define an optional argument that defines the ip address, $inetAddr, "xx.xx.xx.xx", of the remote machine to which data is sent and the port on remote machine awaiting tcp,$port (for server applications);
• -precision is used to set the optional argument that defines the number of significant digits that in default is 6;
• -time is used to place the domain time in first entry of each data line (i.e. first column) that in default is omitted;
• -iNode is used to set the arguments $inode1$inode2 ... that define the tags of set of I nodes for which drift is being recorded;
• -jNode is used to set the arguments $jnode1$jnode2 ... that define the tags of set of J nodes for which drift is being recorded;
• -dof is used to set the arguments $dof1$dof2 ... defining the DoFs whose response is requested. Valid range is from 1 through ndf (the number of nodal degrees of freedom);
• -perpDirn si used to set the arguments $perpDirn1$perpDirn2 ... defining the set of perpendicular global directions (1=X, 2=Y, 3=Z). This input is needed to calculate the length between the nodes whose drift is calculated.

In this example, the drift recorder is used to output lateral drifts into file Drift.out between nodes 1 and 2. The following code lines are used to create the two node recorders:

# Create a Recorder object for drift:
recorder Drift -file Data/Drift.out -time -iNode 1 -jNode 3 -dof 1 -perpDirn 2

The first column of the file Drift.out is the time, and the second column is the lateral drift.

1.2.5.3 Element recorder

The command “recorder Element <-file $fileName> <-xml$fileName> <-binary $fileName> <-precision$nSD> <-time> <-dT $deltaT> <-closeOnWrite> <-ele ($ele1 $ele2 ...)> <-eleRange$startEle $endEle> <-region$regTag> $arg1$arg2 ...” creates an element recorder with output filename named $fileName in the format: textual (-file option), xml format (-xml option) or binary (-binary option). One of the output should be mandatory defined. The switch: • -precision is used to set the optional argument that defines the number of significant digits that in default is 6; • -time is used to place the domain time in first entry of each data line (i.e. first column) that in default is omitted; • -dT is used to set the optional argument defining the time interval for recording,$deltaT, that is in default recording at every time step;
• -closeOnWrite is used to instruct the recorder to invoke a close on the data handler after every time-step (a file it will close the file on every step and then re-open it for the next step);
• -ele, -eleRange, -region. One of these should be mandatory defined:
1. -ele defines the elements with tag $ele1$ele2 ... to be recorded;
2. -eleRange defines the nodes range from tag $startEle to$endEle to be recorded;
3. -region defines the elements as those belonging to a region defined with tag $regionTag using the command regions; •$arg1 $arg2 are the arguments defining the response type required. The definition of the arguments depends on the element used. For instance, the valid queries to an elastic beam-column element (that used in this example) when creating an ElementRecorder object are force. In this example, the node recorder is used to output the end forces of all the elements from (1, 2 and 3) into the textual file eleGlobal.out. These forces correspond to the global coordinate axes orientation. Again, this file is located in the subfolder Data created in Section 1. The following code lines are used to create the element recorder: # Create a Recorder object for element forces: recorder Element -file Data/eleGlobal.out -time -ele 1 2 3 forces The first column of the file eleGlobal.out is the time, and the last eighteen columns are the end forces (six for each element, three for each end node) of the three elements (1, 2 and 3). 1.2.6 Analysis In order to start the Analysis section, the following lines can be used: # ANALYSIS # ------------------------------ In OpenSEES each Analysis object is composed of several component objects, which define how the analysis is performed. The component classes consist of the following: • Constraints: determines how the constraint equations are enforced in the analysis and how it handles the boundary conditions/imposed displacements; • DOF Numberer: determines the mapping between equation numbers and degrees-of-freedom; • System of Equations: within the solution algorithm, it specifies how to store and solve the system of equations in the analysis; • Convergence Test: determines when convergence has been achieved; • Algorithm: determines the sequence of steps taken to solve the non-linear equation at the current time step; • Analysis: defines what type of analysis had to be performed; • Integrator: determines the predictive step for time t + dt; • Analyze: to run the solver. Before to start the analysis, the above-mentioned classes should be set. In order to start the Analysis definition, the following lines can be used: # Analysis definitions: 1.2.6.1 Constraints The command “constraints constraintType? arg1? ...” defines the ConstraintHandler type, constraintType?, with arguments depending on the constraintType?. The following ConstraintHandler types are available in OpenSEES: • Plain Constraint; • Lagrange Multipliers; • Penalty Method; • Transformation Method. In the case of a frame with a total fixity (all DOFs are constrained) at the nodes 1 and 2, a Plain Constraint can be used; this will create a PlainHandler which is only capable of enforcing homogeneous single-point constraints. The following code lines are used to set a Plain Constraint : # Create the constraint handler: constraints Plain 1.2.6.2 DOF Numberer The command “numberer numbererType?” defines the DOFNumberer object type, numbererType?. The following DOFNumberer object types are available in OpenSEES: • Plain Numberer; • Reverse Cuthill-McKee Numberer; • Alternative_Minimum_Degree Numberer. Since the model is very simple and small, Plain Numberer will be used. The following code lines are used to set a Plain Numberer: # Create the DOF numberer: numberer Plain 1.2.6.3 System The command “system systemType? arg1? ...” defines the Solver type, systemType?, with arguments depending on the constraintType?. The following solver types are available in OpenSEES: • BandGeneral SOE; • BandSPD SOE; • ProfileSPD SOE; • SuperLU SOE; • UmfPack SOE; • FullGeneral; • SparseSYM SOE; • Mumps; • Cusp. In this example, to store and solve the system of equations during the analysis BandSPD solver is used. As the name implies, this class is used for symmetric positive definite matrix systems which have a banded profile. The following command is used to construct such a system with SPD using a band storage scheme: # Create the system of equation: system BandSPD 1.2.6.4 Test The command “test testType? arg1? ...” defines the ConvergenceTest object, testType?, with arguments depending on the testType?. It should be highlighted that only certain SolutionAlgorithm objects require a ConvergenceTest object to determine if convergence has been achieved at the end of an iteration step. For instance, in linear analysis this object is not required. In this example, the frame is linear and the convergence test is not required and it will not added: # No test is required! # Create the convergenge test: # No test is required! 1.2.6.5 Algorithm The command “algorithm algorithmType? arg1? ...” is used to construct a SolutionAlgorithm object with type algorithmType?, with arguments depending on the algorithmType?. The following algorithm types are available in OpenSEES: • Linear Algorithm; • Newton Algorithm; • Newton with Line Search Algorithm; • Modified Newton Algorithm; • Krylov-Newton Algorithm; • Secant Newton Algorithm; • BFGS Algorithm; • Broyden Algorithm; Since the frame is elastic the system of equation can be solved in one iteration. Thus, the linear algorithm will be used to solve the system of equations. The command “algorithm Linear <-initial or -secant> <-factorOnce>” construct a Linear algorithm object which takes one iteration to solve the system of equations. The optional switches are: • -initial or -secant: • -initial to indicate to use secant stiffness; • -secant to indicate to use initial stiffness; • -factorOnce to indicate to only set up and factor matrix once; in case of an elastic systems, it is highly advantageous to use -factorOnce as the tangent matrix typically will not change during the analysis. The following command is used to define a linear algorithm: # Create the solution algorithm: algorithm Linear 1.2.6.6 Integrator The command “integrator$integratorType? arg1? ...” is is used to construct the Integrator object with type, $integratorType?, with arguments depending on the$integratorType?. The Integrator object determines the meaning of the terms in the system of equation object Ax = B, i.e. system of equation object. The following integrator types are available in OpenSEES:

• Static Integrators:
• Displacement Control;
• Minimum Unbalanced Displacement Norm;
• Arc-Length Control;
• Transient Integrators:
• Central Difference;
• Newmark Method;
• Hilber-Hughes-Taylor Method;
• Generalized Alpha Method;
• TRBDF2.

Since the analysis is static and specific load (1000N) is to be applied, load control integrator will be used in this example. The load factor increment (l) is set to 1 since the full load of 1000N is to be applied in 1 analysis steps. The command “integrator LoadControl $lambda <$numIter $minLambda$maxLambda>” defines a LoadControl integrator object with load factor increment l, $lambda. The following optional arguments are available:$numIter defines the number of iterations the user would like to occur in the solution algorithm in default is 1.0; $minLambda defines the min step-size the user will allow;$maxLambda defines the max step-size the user will allow. The following command is used to define a LoadControl scheme using steps of 1.0:

# Create the integration scheme:

The command “analysis analysisType?” is used to construct the Analysis object of type analysisType?. The following analysis types are available in OpenSEES:

Currently 3 valid options:

• Static - for static analysis;
• Transient - for transient analysis with constant time step;
• VariableTransient - for transient analysis with variable time step.
1.2.6.7 Analysis

The load is a static type of the load and thus a static analysis object is employed. The following command is used to define a static analysis:

# Create the analysis object:
analysis Static

With this all analysis objects are defined, so the analysis can be performed. The command “analyze $numIncr <$dt> <$dtMin$dtMax $Jd>” performs the analysis with$numIncr number of analysis steps to perform. The following optional arguments are available: $dt is the time-step increment and it is required if transient or variable transient analysis;$dtMin and $dtMax define the minimum and maximum time steps, respectively;$Jd defines the number of iterations performed at each step. They ($dtMin$dtMax $Jd) are required if a variable time step transient analysis was specified. 1.2.6.8 Analyze The analysis is performed by invoking the command analyze and by defining the number of analysis steps to be performed (1 for this example as the loads are increase from 0 to the final value). The following code lines are used to start the analysis: # Perform the analysis: analyze 1 It should be highlighted that the command “analyze” produces a return (output). The output is: • 0 if the analysis is successful; • < 0 if the analysis is not successful. This output can be used to check if the analysis is correctly finished. For instance, the following code lines can be used to perform 1 step of analysis and to set the variable ok equal to 0 if the analysis is successful or to a negative value otherwise: set ok [analyze 1] Subsequently, the variable ok can be recalled to check if the analysis was successful. 1.2.7 Screen print In order to start the Screen print section, the following lines can be used: # SCREEN PRINT # ------------------------------ In addition to using recorders, it is possible to specify output using the print and puts commands. When no file identifiers are provided, these commands will print results to the screen. The command “puts$string” takes the single string argument, $string, and write it to the terminal. The quotation marks " are used to group the words into a single argument, { } braces could also have been used. The following command is used to print on the screen the final displacements at node 3: # Print the final displacements at node 3: puts "node␣3␣displacement:␣[nodeDisp␣3]" The following command is used to print on the screen the the final displacements at node 4: # Print the final displacements at node 4: puts "node␣4␣displacement:␣[nodeDisp␣4]" The following command is used to print on the screen the elastic modulus (i.e. the assigned value of the variable E): # Print the value of the elastic modulus: puts "E=␣$E"

The command “print” can be used to:

• To print all objects of the domain: “print <$fileName>”; • To print node information: “print <$fileName> -node <-flag $flag> <$node1 $node2 ...>”; • To print element information: “print <$fileName> -ele <-flag $flag> <$ele1 $ele2 ...>” where$fileName is the optional argument defining name of file to which data will be sent overwrites existing file and in default, it does not create a file; $flag is an optional argument that is an integer flag to be sent to the print() method, depending on the node and element type (optional). The following command is used to print the current state at node 3: # Print the current state at node 3: print node 3 The following command is used to print the current state at all elements: # Print the current state at all elements: print -ele The following command is used to print a string indicating that the execution of the code is terminated: # Print a string indicating that the execution of the code is terminated: puts "The␣execution␣of␣the␣code␣is␣terminated" 1.3 Results The results obtained running the code are the following: • file DFree.out 1 121.234 0.0144288 -0.0103984 121.234 -0.0144288 -0.0103984 • file Rbase.out -1000 -1515.02 2.72746e+06 -1000 1515.02 2.72746e+06 • file drift.out 1 0.0242468 • file eleGlobal.out -1000 -1515.02 2.72746e+06 1000 1515.02 2.27254e+06 ... -1000 1515.02 2.72746e+06 1000 -1515.02 2.27254e+06 ... -2.4869e-09 -1515.02 -2.27254e+06 2.4869e-09 1515.02 -2.27254e+06 Moreover, the code produces the following text in the screen: node 3 displacement: 121.23398303024539757189 0.01442879988458356175 -0.01039835511682321752 node 4 displacement: 121.23398303024541178274 -0.01442879988458355654 -0.01039835511682321752 E= 2.1e5 Node: 3 Coordinates : 0 5000 Disps: 121.234 0.0144288 -0.0103984 unbalanced Load: 1000 0 0 reaction: -1.51977e-09 6.82121e-13 -4.65661e-10 ID : 3 4 5 ElasticBeam2d:1 Connected Nodes: 1 3 CoordTransf: 1 mass density: 0, cMass: 0 End 1 Forces (P V M): -1515.02 1000 2.72746e+06 End 2 Forces (P V M): 1515.02 -1000 2.27254e+06 ElasticBeam2d: 2 Connected Nodes: 2 4 CoordTransf: 1 mass density: 0, cMass: 0 End 1 Forces (P V M): 1515.02 1000 2.72746e+06 End 2 Forces (P V M): -1515.02 -1000 2.27254e+06 ElasticBeam2d: 3 Connected Nodes: 3 4 CoordTransf: 1 mass density: 0, cMass: 0 End 1 Forces (P V M): -2.4869e-09 -1515.02 -2.27254e+06 End 2 Forces (P V M): 2.4869e-09 1515.02 -2.27254e+06 The execution of the code is terminated 1.4 Extensions 1.4.1 Example of use of procedure in an external file The procedure is a useful tool available from the Tcl language. A procedure is a generalized function/subroutine using arguments. Whenever the Tcl procedure is invoked, the contents of body will be executed by the Tcl interpreter. For instance, in order to compute the area and the inertia of the cross-section in Section 1.2.2, two procedures can be defined as: # Procedure for the area of the section: proc area {B H} {return [expr$B*$H]} # Procedure for the inertia of the section; proc inertia {B H} {return [expr 1./12.*$B*pow($H,3)]} After the definition of the procedures the area and the inertia of the cross-section can be calculated as: # Compute area and anertia: set A [area$B $H] set I [inertia$B $H] The previous lines can be used to define the area and the inertia in an automatic way. This procedure can be easier when many sections should be defined. Moreover, the code with the procedures can be used in an external file. For instance, it can be defined a file named procedure.tcl with the following content: # Procedure for the area of the section: proc area {B H} {return [expr$B*$H]} Moreover, the code can be included in the main file calling using the source command the file procedure.tcl and using the procedure area as follows: # Source the external file procedure.tcl: source procedure.tcl # Call the area: set A [area$B $H] Please note that the filename depending on the operative system and settings must have specified the full directory tree or only the local one. 1.4.2 Variation of the loads during the analysis To apply different loads during the analysis, different load patterns should be defined. Before to apply a new load the previously defined load should be set equal to zero. The command “loadConst <-time$pseudoTime>” is used to set the loads constant in the domain and to also set the time in the domain. When setting the loads constant, the procedure will invoke setLoadConst() on all LoadPattern objects which exist in the domain at the time the command is called. If the optional switch -time is used the pseudoTime is set at equal to $pseudoTime. For instance, to add a vertical load to construct a load pattern with tag 1 and time series tag 1, and populate it with two horizontal forces (in the x- direction) applied to the nodes with tag 3 and 4 of reference magnitude equal to the previously defined variable F3 and F4 (Figure 1.1.1), the following code lines are used: # Create a Plain load pattern with a linear TimeSeries: pattern Plain 1 1 { load 3$F3 0 0
load 4 $F4 0 0 } Then, to perform the analysis using this load the following code lines are used: # Perform the analysis: analyze 1 After performing the analysis with the horizontal load on the model (Pattern tag 1), the time in the domain is reset to 0.0 and the current value of all loads acting are held constant: # Set previous loads constant and reset the time in the domain: loadConst -time 0.0 It should be noted that is necessary to reset the time to zero as the actual load in the step is computed as l = F(t) = Cfactor ×t since a linear time series is adopted. A new load pattern with tag 2 with a linear time series (tag 1) and vertical loads acting at nodes 3 and 4 equal to 1000N is then added to the model: # Create a Plain load pattern with a linear TimeSeries: pattern Plain 2 1 { load 3 0 -1000 0 load 4 0 -1000 0 } Then, to perform the analysis using this load the following code lines are used: # Perform the analysis: analyze 1 Again, after performing the analysis, the time in the domain is reset to 0.0 and the current value of all loads acting are held constant: # Set previous loads constant and reset the time in the domain: loadConst -time 0.0 A new analysis is performed: # Perform the analysis: analyze 1 The output file Dfree.out obtained after running the input file using the developed program is shown below. 1 121.234 0.0144288 -0.0103984 121.234 -0.0144288 -0.0103984 1 121.234 0.00490499 -0.0103984 121.234 -0.0239526 -0.0103984 1 121.234 0.00490499 -0.0103984 121.234 -0.0239526 -0.0103984 In the first column is reported the pseudo time. That in all the steps the pseudo time is equal to 1 since using loadconst it is reset to zero, can be seen. Moreover, in first row the displacements induced by the horizontal load are shown. On the other hand, in the second row, the effect induced by the vertical loads can be seen, i.e. only vertical displacements varies: columns 4 and 5. In particular, the difference in terms of vertical displacements is the same, i.e. 0.0095 (0.0144288 - 0.00490499 or -0.0144288 -). Finally, in the last step there are no effects because the current value of all acting loads are held constant and no loads (i.e. new patterns) are applied in the step. It should be highlighted that different output files can be created in the steps by removing the recorders and creating new ones. The command “remove recorders ” removes all the recorder. The command “remove recorder <$tag>” remove the recorder with tag $tag. It should be highlighted that the tag of the recorder is given as output when the recorder is defined. Here is an example on how to get the tag of a recorder to output displacements of the DoFs from 1 to 3 of the free nodes into the textual file DFree.out: # Create a Recorder object for the nodal displacements: set recordertag [recorder Node -file Data/DFree.out -time -node 3 4 -dof 1 2 3 disp] To remove this recorder, the following code lines can be used: # Remove the recorder with tag$recordertag:
analyze $numSteps } It should be highlighted that using the latter solution more cycles can be programmed using less lines of code. 1.5 Final code # TITLE # ------------------------------ # Frame (Linear and Elastic) # Units: N, mm, sec # Remove existing model: wipe # Create data directories: file mkdir Data # INPUTS # ------------------------------ # Define the length of the beam and of the column: set L 5000 set L2 3000 # Define cross-section: set B 50 set H 50 # Define elastic modulus: set E 2.1e5 # Define horizontal forces: set F3 1000 set F4 1000 # Compute area and inertia: set A [expr$B*$H] set I [expr 1./12.*$B*pow($H,3)] # MODEL # ------------------------------ # Create ModelBuilder: model BasicBuilder -ndm 2 -ndf 3 # Create nodes: node 1 0.0 0.0 node 2$L2 0.0
node 3 0.0 $L node 4$L2 $L # Set the boundary conditions: fix 1 1 1 1 fix 2 1 1 1 fix 3 0 0 0 fix 4 0 0 0 # Define elements: # Define geometric transformation: geomTransf Linear 1 # Create elements: element elasticBeamColumn 1 1 3$A $E$I 1;
element elasticBeamColumn 2 2 4 $A$E $I 1; element elasticBeamColumn 3 3 4$A $E$I 1;

# ------------------------------

# Create TimeSeries object:
timeSeries Linear 1

# Create a Plain load pattern with a linear TimeSeries:
pattern Plain 1 1 {
load 3 $F3 0 0 load 4$F4 0 0

# RECORDER
# ------------------------------

# Create a Recorder object for the nodal displacements:
recorder Node -file Data/DFree.out -time -node 3 4 -dof 1 2 3 disp

# Create a Recorder object for the nodal reactions:
recorder Node -file Data/RBase.out -time -node 1 2 -dof 1 2 3 reaction

# Create a Recorder object for drift:
recorder Drift -file Data/Drift.out -time -iNode 1 -jNode 3 -dof 1 -perpDirn 2

# Create a Recorder object for element forces:
recorder Element -file Data/eleGlobal.out -time -ele 1 2 3 forces

# ANALYSIS
# ------------------------------

# Analysis definitions:

# Create the constraint handler:
constraints Plain

# Create the DOF numberer:
numberer Plain

# Create the system of equation:
system BandSPD

# Create the convergenge test:
# No test is required!

# Create the solution algorithm:
algorithm Linear

# Create the integration scheme:

# Create the analysis object:
analysis Static

# Perform the analysis:
analyze 1

# SCREEN PRINT
# ------------------------------

# Print the final displacements at node 3:
puts "node␣3␣displacement:␣[nodeDisp␣3]"
# Print the final displacements at node 4:
puts "node␣4␣displacement:␣[nodeDisp␣4]"
# Print the value of the elastic modulus:
puts "E=␣\$E"
# Print the current state at node 3:
print node 3
# Print the current state at all elements:
print -ele
# Print a string indicating that the execution of the code is terminated:
puts "The␣execution␣of␣the␣code␣is␣terminated"

Start typing and press Enter to search