├── .gitattributes ├── .gitignore ├── .travis.yml ├── OpenSeesAPI ├── Analysis │ ├── Algorithm.py │ ├── Analysis.py │ ├── Analyze.py │ ├── Constraints.py │ ├── Eigen.py │ ├── Integrator.py │ ├── Numberer.py │ ├── System.py │ ├── Test.py │ └── __init__.py ├── Database.py ├── Helpers │ ├── Materials.py │ ├── Sections.py │ ├── SolutionAlgorithms.py │ └── __init__.py ├── Misc.py ├── Model │ ├── BasicBuilder.py │ ├── Constraint.py │ ├── Element │ │ ├── Element.py │ │ ├── GeomTransf.py │ │ ├── Material │ │ │ ├── NDMaterial.py │ │ │ ├── Section.py │ │ │ ├── UniaxialMaterial.py │ │ │ └── __init__.py │ │ └── __init__.py │ ├── Node.py │ ├── Pattern.py │ ├── TimeSeries.py │ └── __init__.py ├── OpenSees.py ├── Output.py ├── TCL.py └── __init__.py ├── README.md ├── TODO.md ├── setup.py └── test ├── SampleScript1.py ├── SampleScript2.py ├── SampleScript3.py ├── SampleScript4.py ├── __init__.py └── test.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | # Byte-compiled / optimized / DLL files 45 | __pycache__/ 46 | *.py[cod] 47 | *$py.class 48 | 49 | # C extensions 50 | *.so 51 | 52 | # Distribution / packaging 53 | .Python 54 | env/ 55 | build/ 56 | develop-eggs/ 57 | dist/ 58 | downloads/ 59 | eggs/ 60 | .eggs/ 61 | lib/ 62 | lib64/ 63 | parts/ 64 | sdist/ 65 | var/ 66 | *.egg-info/ 67 | .installed.cfg 68 | *.egg 69 | 70 | # PyInstaller 71 | # Usually these files are written by a python script from a template 72 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 73 | *.manifest 74 | *.spec 75 | 76 | # Installer logs 77 | pip-log.txt 78 | pip-delete-this-directory.txt 79 | 80 | # Unit test / coverage reports 81 | htmlcov/ 82 | .tox/ 83 | .coverage 84 | .coverage.* 85 | .cache 86 | nosetests.xml 87 | coverage.xml 88 | *,cover 89 | 90 | # Translations 91 | *.mo 92 | *.pot 93 | *.pyc 94 | *.pyo 95 | 96 | # Django stuff: 97 | *.log 98 | 99 | # Sphinx documentation 100 | docs/_build/ 101 | 102 | # PyBuilder 103 | target/ 104 | 105 | # Setuptools distribution folder. 106 | /dist/ 107 | 108 | # Python egg metadata, regenerated from source files by setuptools. 109 | /*.egg-info# Setuptools distribution folder. 110 | /dist/ 111 | 112 | # Python egg metadata, regenerated from source files by setuptools. 113 | /*.egg-info 114 | 115 | # Ignore all the files that would be made if you run OpenSees 116 | *.tcl 117 | *.dat 118 | 119 | # Ignore all of pycharms idea-intellij files 120 | .idea -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: python 4 | python: 5 | - "2.6" 6 | - "2.7" 7 | # - "3.2" 8 | # - "3.3" 9 | # - "3.4" 10 | - "3.5" 11 | # - "3.5-dev" # 3.5 development branch 12 | # - "nightly" # currently points to 3.6-dev 13 | # command to install dependencies 14 | install: "pip install ." 15 | ## command to run tests 16 | script: python test/test.py -------------------------------------------------------------------------------- /OpenSeesAPI/Analysis/Algorithm.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | 4 | This command is used to construct a SolutionAlgorithm object, which determines the sequence of steps taken to solve the non-linear equation. 5 | algorithm algorithmType? arg1? ... 6 | The type of solution algorithm created and the additional arguments required depends on the algorithmType? provided in the command. 7 | 8 | The following contain information about algorithmType? and the args required for each of the available algorithm types: 9 | Linear Algorithm 10 | Newton Algorithm 11 | Newton with Line Search Algorithm 12 | Modified Newton Algorithm 13 | Krylov-Newton Algorithm 14 | Secant Newton Algorithm 15 | BFGS Algorithm 16 | Broyden Algorithm 17 | """ 18 | 19 | __author__ = 'Nasser' 20 | 21 | from OpenSeesAPI.OpenSees import OpenSees 22 | 23 | class Linear(OpenSees): 24 | """ 25 | This command is used to construct a Linear algorithm object which takes one iteration to solve the system of equations. 26 | \Delta U = - K^{-1}R(U),\! 27 | 28 | algorithm Linear <-initial> <-factorOnce> 29 | 30 | -secant optional flag to indicate to use secant stiffness 31 | -initial optional flag to indicate to use initial stiffness 32 | -factorOnce optional flag to indicate to only set up and factor matrix once 33 | """ 34 | def __init__(self): 35 | self._CommandLine = 'algorithm Linear' 36 | 37 | class Newton(OpenSees): 38 | """ 39 | This command is used to construct a NewtonRaphson algorithm object which is uses the Newton-Raphson algorithm to solve the nonlinear residual equation. The Newton-Raphson method is the most widely used and most robust method for solving nonlinear algebraic equations. The command is of the following form: 40 | algorithm Newton <-initial> <-initialThenCurrent> 41 | 42 | -initial optional flag to indicate to use initial stiffness iterations 43 | -initialThenCurrent optional flag to indicate to use initial stiffness on first step, then use current stiffness for subsequent steps 44 | """ 45 | def __init__(self, Initial=False,InitialThenCurrent=False): 46 | self._Initial = Initial 47 | self._InitialThenCurrent = InitialThenCurrent 48 | if self._Initial: 49 | self._CommandLine = 'algorithm Newton -initial' 50 | elif self._InitialThenCurrent: 51 | self._CommandLine = 'algorithm Newton -initialThenCurrent' 52 | else: 53 | self._CommandLine = 'algorithm Newton' 54 | 55 | class ModifiedNewton(OpenSees): 56 | """ 57 | This command is used to construct a ModifiedNewton algorithm object, which uses the modified newton-raphson algorithm to solve the nonlinear residual equation. The command is of the following form: 58 | algorithm ModifiedNewton <-initial> 59 | 60 | -initial optional flag to indicate to use initial stiffness iterations. 61 | 62 | """ 63 | def __init__(self, Initial=False): 64 | self._Initial = Initial 65 | if self._Initial: 66 | self._CommandLine = 'algorithm ModifiedNewton -initial' 67 | else: 68 | self._CommandLine = 'algorithm ModifiedNewton' 69 | 70 | class NewtonLineSearch(OpenSees): 71 | """ 72 | This command is used to construct a NewtonLineSearch algorithm object which introduces line search to the Newton-Raphson algorithm to solve the nonlinear residual equation. Line search increases the effectiveness of the Newton method when convergence is slow due to roughness of the residual. The command is of the following form: 73 | algorithm NewtonLineSearch <-type $typeSearch> <-tol $tol> <-maxIter $maxIter> <-minEta $minEta> <-maxEta $maxEta> 74 | 75 | $typeSearch line search algorithm. optional default is InitialInterpoled. valid types are: 76 | Bisection, Secant, RegulaFalsi, InitialInterpolated 77 | $tol tolerance for search. optional, defeulat = 0.8 78 | $maxIter max num of iterations to try. optional, default = 10 79 | $minEta a min \eta\! value. optional, default = 0.1 80 | $maxEta a max \eta\! value. optional, default = 10.0 81 | """ 82 | def __init__(self, typeSearch='InitialInterpoled', Tolerance=0.8, MaxIteration=10, MinEta=0.1, MaxEta=10.): 83 | self._typeSearch = typeSearch 84 | self._Tolerance = Tolerance 85 | self._MaxIteration = MaxIteration 86 | self._MinEta = MinEta 87 | self._MaxEta = MaxEta 88 | self._CommandLine = 'algorithm NewtonLineSearch -type %s -tol %e -maxIter %d -minEta %f -maxEta %f'%(self._typeSearch,self._Tolerance,self._MaxIteration,self._MinEta,self._MaxEta) 89 | 90 | class KrylovNewton(OpenSees): 91 | """ 92 | This command is used to construct a KrylovNewton algorithm object which uses a Krylov subspace accelerator to accelerate the convergence of the modified newton method. The command is of the following form: 93 | algorithm KrylovNewton <-iterate $tangIter> <-increment $tangIncr> <-maxDim $maxDim> 94 | 95 | $tangIter tangent to iterate on, options are current, initial, noTangent. default is current. 96 | $tangIncr tangent to increment on, options are current, initial, noTangent. default is current 97 | $maxDim max number of iterations until the tangent is reformed and the acceleration restarts (default = 3). 98 | """ 99 | def __init__(self, TangIter=None, TangIncr=None, MaxDim=None): 100 | self._TangIter = TangIter 101 | self._TangIncr = TangIncr 102 | self._MaxDim = MaxDim 103 | 104 | self._Options = '' 105 | if self._TangIter != None: 106 | self._Options += '-iterate %s'%self._TangIter 107 | if self._TangIter != None: 108 | self._Options += '-increment %s'%self._TangIncr 109 | if self._MaxDim != None: 110 | self._Options += '-maxDim %s'%self._MaxDim 111 | 112 | self._CommandLine = 'algorithm KrylovNewton %s'%(self._Options) 113 | 114 | class BFGS(OpenSees): 115 | """ 116 | This command is used to construct a(BFGS) algorithm object. The BFGS method is one of the most effective matrix-update or quasi Newton methods for iteration on a nonlinear system of equations. The method computes new search directions at each iteration step based on the initial jacobian, and subsequent trial solutions. The unlike regular Newton-Raphson does not require the tangent matrix be reformulated and refactored at every iteration, however unlike ModifiedNewton it does not rely on the tangent matrix from a previous iteration. 117 | 118 | algorithm BFGS 119 | """ 120 | def __init__(self): 121 | self._CommandLine = 'algorithm BFGS' 122 | 123 | class Broyden(OpenSees): 124 | """ 125 | This command is used to construct a Broyden algorithm object for general unsymmetric systems which performs successive rank-one updates of the tangent at the first iteration of the current time step. 126 | 127 | algorithm Broyden <$count> 128 | 129 | $count number of iterations within a time step until a new tangent is formed 130 | """ 131 | def __init__(self, Count): 132 | self._Count = Count 133 | self._CommandLine = 'algorithm Broyden %d'%self._Count 134 | -------------------------------------------------------------------------------- /OpenSeesAPI/Analysis/Analysis.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | analysis analysisType? 4 | $analysisType char string identifying type of analysis object to be constructed. Currently 3 valid options: 5 | Static - for static analysis 6 | Transient - for transient analysis with constant time step 7 | VariableTransient - for transient analysis with variable time step 8 | NOTE: 9 | If the component objects are not defined before hand, the command automatically creates default component objects and issues warning messages to this effect. The number of warning messages depends on the number of component objects that are undefined. 10 | """ 11 | 12 | __author__ = 'Nasser' 13 | 14 | from OpenSeesAPI.OpenSees import OpenSees 15 | 16 | class Static(OpenSees): 17 | def __init__(self): 18 | self._CommandLine = 'analysis Static' 19 | 20 | class Transient(OpenSees): 21 | def __init__(self): 22 | self._CommandLine = 'analysis Transient' 23 | 24 | class VariableTransient(OpenSees): 25 | def __init__(self): 26 | self._CommandLine = 'analysis variableTransient' 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /OpenSeesAPI/Analysis/Analyze.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | This command is used to perform the analysis. 4 | analyze $numIncr <$dt> <$dtMin $dtMax $Jd> 5 | $numIncr number of analysis steps to perform. 6 | $dt time-step increment. Required if transient or variable transient analysis 7 | $dtMin $dtMax minimum and maximum time steps. Required if a variable time step transient analysis was specified. 8 | $Jd number of iterations user would like performed at each step. The variable transient analysis will change current time step if last analysis step took more or less iterations than this to converge. 9 | Required if a variable time step transient analysis was specified. 10 | RETURNS: 11 | 0 if successful 12 | <0 if NOT successful 13 | 14 | EXAMPLE: 15 | set ok [anlayze 10]; # perform 10 static analysis steps 16 | set ok [analyze 2000 0.01]; # perform 2000 transient time steps at 0.01 increments 17 | 18 | """ 19 | 20 | __author__ = 'Nasser' 21 | 22 | 23 | from OpenSeesAPI.OpenSees import OpenSees 24 | 25 | class Analyze(OpenSees): 26 | def __init__(self, Steps, Increments=None): 27 | self._Steps = Steps 28 | self._Increments = Increments 29 | 30 | @property 31 | def CommandLine(self): 32 | if self._Increments == None: 33 | self._CommandLine = 'set ok [analyze %d]'%self._Steps 34 | else: 35 | self._CommandLine = 'set ok [analyze %d %f]'%(self._Steps, self._Increments) 36 | 37 | return self._CommandLine 38 | 39 | -------------------------------------------------------------------------------- /OpenSeesAPI/Analysis/Constraints.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | 4 | The type of ConstraintHandler created and the additional arguments required depends on the constraintType? provided in the command. 5 | 6 | The following contain information about numbererType? and the args required for each of the available constraint handler types: 7 | Plain Constraints 8 | Lagrange Multipliers 9 | Penalty Method 10 | Transformation Method 11 | 12 | """ 13 | 14 | __author__ = 'Nasser' 15 | 16 | from OpenSeesAPI.OpenSees import OpenSees 17 | 18 | class Plain(OpenSees): 19 | """ 20 | This command is used to construct a Plain constraint handler. A plain constraint handler can only enforce homogeneous single point constraints (fix command) and multi-point constraints constructed where the constraint matrix is equal to the identity (equalDOF command). The following is the command to construct a plain constraint handler: 21 | """ 22 | "" 23 | def __init__(self): 24 | self._CommandLine = 'constraints Plain' 25 | 26 | class Lagrange(OpenSees): 27 | """ 28 | This command is used to construct a LagrangeMultiplier constraint handler, which enforces the constraints by introducing lagrange multiplies to the system of equation. The following is the command to construct a plain constraint handler: 29 | 30 | constraints Lagrange <$alphaS $alphaM > 31 | 32 | $alphaS alphaS factor on singe points. optional, default = 1.0 33 | $alphaM alphaM factor on multi-points, optional default = 1.0; 34 | """ 35 | def __init__(self, AlphaS=1.0, AlphaM=1.0): 36 | self._AlphaS = AlphaS 37 | self._AlphaM = AlphaM 38 | 39 | @property 40 | def CommandLine(self): 41 | self._CommandLine = 'constraints Lagrange %f %f'%(self._AlphaS, self._AlphaM) 42 | return self._CommandLine 43 | 44 | class Penalty(OpenSees): 45 | """ 46 | This command is used to construct a Penalty constraint handler, which enforces the constraints using the penalty method. The following is the command to construct a penalty constraint handler: 47 | 48 | constraints Penalty $alphaS $alphaM 49 | 50 | $alphaS penalty alphaS factor on single point constraints 51 | $alphaM penalty alphaM factor on multi-point constraints 52 | """ 53 | def __init__(self, AlphaS, AlphaM): 54 | self._AlphasS = AlphaS 55 | self._AlphaM = AlphaM 56 | 57 | @property 58 | def CommandLine(self): 59 | self._CommandLine = 'constraints Penalty %f %f'%(self._AlphasS, self._AlphaM) 60 | return self._CommandLine 61 | 62 | class Transformation(OpenSees): 63 | """ 64 | This command is used to construct a transformation constraint handler, which enforces the constraints using the transformation method. The following is the command to construct a transformation constraint handler: 65 | 66 | constraints Transformation 67 | 68 | NOTES: 69 | The single-point constraints when using the transformation method are done directly. The matrix equation is not manipulated to enforce them, rather the trial displacements are set directly at the nodes at the start of each analysis step. 70 | Great care must be taken when multiple constraints are being enforced as the transformation method does not follow constraints: 71 | 1) If a node is fixed, constrain it with the fix command and not equalDOF or other type of constraint. 72 | 2) If multiple nodes are constrained, make sure that the retained node is not constrained in any other constraint. 73 | And remember if a node is constrained to multiple nodes in your model it probably means you have messed up. 74 | """ 75 | def __init__(self): 76 | self._CommandLine = 'constraints Transformation' -------------------------------------------------------------------------------- /OpenSeesAPI/Analysis/Eigen.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | eigen 4 | """ 5 | 6 | __author__ = 'Nasser' 7 | 8 | from OpenSeesAPI.OpenSees import OpenSees 9 | 10 | class Eigen(OpenSees): 11 | """ 12 | This command is used to perform the analysis. 13 | eigen <$solver> $numEigenvalues 14 | $numEigenvalues number of eigenvalues required 15 | $solver optional string detailing type of solver: -genBandArpack, -symmBandLapack, -fullGenLapack (default: -genBandArpack) 16 | 17 | RETURNS: 18 | a tcl string containg eigenvalues. 19 | """ 20 | def __init__(self, NoOfModes, symmBandLapack=False, fullGenLapack=False): 21 | self._NoOfModes = NoOfModes 22 | self._Optional = '' 23 | if symmBandLapack == True: 24 | self._Optional = '-symmBandLapack' 25 | elif fullGenLapack==True: 26 | self._Optional = '-fullGenLapack' 27 | self._CommandLine = 'set pi [expr 2.0*asin(1.0)]; \n' 28 | self._CommandLine += 'set nModes %d; \n'%(self._NoOfModes) 29 | self._CommandLine += 'set lambdaN [eigen %s %d]; \n'%(self._Optional,self._NoOfModes) 30 | for i in range(0,self._NoOfModes): 31 | self._CommandLine += 'set lambdaN%d [lindex $lambdaN [expr %d]]; \n'%(i+1,i) 32 | for i in range(0,self._NoOfModes): 33 | self._CommandLine += 'set w%d [expr pow($lambdaN%d,0.5)]; \n'%(i+1,i+1) 34 | for i in range(0,self._NoOfModes): 35 | self._CommandLine += 'set T%d [expr 2.0*$pi/$w%d]; \n'%(i+1,i+1) 36 | for i in range(0,self._NoOfModes): 37 | self._CommandLine += 'puts "T%d = $T%d s" \n'%(i+1,i+1) 38 | -------------------------------------------------------------------------------- /OpenSeesAPI/Analysis/Integrator.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | This command is used to construct the Integrator object. The Integrator object determines the meaning of the terms in the system of equation object Ax=B. 4 | The Integrator object is used for the following: 5 | * determine the predictive step for time t+dt 6 | * specify the tangent matrix and residual vector at any iteration 7 | * determine the corrective step based on the displacement increment dU 8 | 9 | The type of integrator used in the analysis is dependent on whether it is a static analysis or transient analysis. 10 | 11 | Static Integrators: 12 | Load Control 13 | Displacement Control 14 | Minimum Unbalanced Displacement Norm 15 | Arc-Length Control 16 | 17 | Transient Integrators: 18 | Central Difference 19 | Newmark Method 20 | Hilber-Hughes-Taylor Method 21 | Generalized Alpha Method 22 | TRBDF2 23 | """ 24 | 25 | __author__ = 'Nasser' 26 | 27 | from OpenSeesAPI.OpenSees import OpenSees 28 | 29 | class Static: 30 | class LoadControl(OpenSees): 31 | """ 32 | integrator LoadControl $lambda <$numIter $minLambda $maxLambda> 33 | $lambda the load factor increment ? 34 | $numIter the number of iterations the user would like to occur in the solution algorithm. Optional, default = 1.0. 35 | $minLambda the min stepsize the user will allow. optional, defualt = ?min = ? 36 | $maxLambda the max stepsize the user will allow. optional, default = ?max = ? 37 | """ 38 | def __init__(self, Lambda, NumIter=None, minLambda=None, maxLambda=None): 39 | self._Lambda = Lambda 40 | self._NumIter = None 41 | self._minLambda = minLambda 42 | self._maxLambda = maxLambda 43 | if self._NumIter == None: 44 | self._CommandLine = 'integrator LoadControl %f'%(self._Lambda) 45 | else: 46 | self._CommandLine = 'integrator LoadControl %f %d %f %f'%(self._Lambda, self._NumIter, self._minLambda, self._maxLambda) 47 | 48 | class DisplacementControl(OpenSees): 49 | """ 50 | integrator DisplacementControl $node $dof $incr <$numIter $?Umin $?Umax> 51 | $node node whose response controls solution 52 | $dof degree of freedom at the node, valid options: 1 through ndf at node. 53 | $incr first displacement increment Udof 54 | $numIter the number of iterations the user would like to occur in the solution algorithm. Optional, default = 1.0. 55 | $Umin the min stepsize the user will allow. optional, defualt = Umin = U0 56 | $Umax the max stepsize the user will allow. optional, default = Umax = U0 57 | """ 58 | def __init__(self, Node, DOF, Increment, Optional=''): 59 | self._Node = Node 60 | self._DOF = DOF 61 | self._Increment = Increment 62 | self._Optional = Optional 63 | self._CommandLine = 'integrator DisplacementControl %d %d %e %s'%(self._Node.id, self._DOF, self._Increment, self._Optional) 64 | 65 | class ArcLength(OpenSees): 66 | """ 67 | This command is used to construct an ArcLength integrator object. In an analysis step with ArcLength we seek to determine the time step that will result in our constraint equation being satisfied. 68 | integrator ArcLength $s $alpha 69 | $s the arcLength. 70 | $alpha a scaling factor on the reference loads. 71 | """ 72 | def __init__(self): 73 | self._CommandLine = 'integrator ArcLength' 74 | 75 | class Transient: 76 | class Newmark(OpenSees): 77 | """ 78 | This command is used to construct a Newmark integrator object. 79 | integrator Newmark $gamma $beta 80 | $gamma gamma factor 81 | $beta beta factor 82 | 83 | EXAMPLE: 84 | 85 | integrator Newmark 0.5 0.25 86 | """ 87 | def __init__(self, Gamma, Beta): 88 | self._Gamma = Gamma 89 | self._Beta = Beta 90 | self._CommandLine = 'integrator Newmark %f %f'%(self._Gamma, self._Beta) 91 | 92 | class HHT(OpenSees): 93 | """ 94 | This command is used to construct a Hilber-Hughes-Taylor (HHT) integration object. This is an implicit method that allows for energy dissipation and second order accuracy (which is not possible with the regular Newmark method). Depending on choices of input parameters, the method can be unconditionally stable. 95 | integrator HHT $alpha <$gamma $beta> 96 | $alpha alpha factor 97 | $gamma gamma factor 98 | $beta beta factor 99 | EXAMPLE: 100 | 101 | integrator HHT 0.9 102 | """ 103 | def __init__(self, Alpha, Gamma=None, Beta=None): 104 | self._Alpha = Alpha 105 | self._Gamma = Gamma 106 | self._Beta = Beta 107 | if Gamma == None and Beta == None: 108 | self._CommandLine = 'integrator HHT %.3f'%(self._Alpha) 109 | else: 110 | self._CommandLine = 'integrator HHT %.3f %.3f %.3f' % (self._Alpha, self._Gamma, self._Beta) 111 | 112 | class CentralDifference(OpenSees): 113 | """ 114 | This command is used to construct a Central Difference integrator object. 115 | integrator CentralDifference 116 | 117 | EXAMPLE: 118 | 119 | integrator CentralDifference 120 | """ 121 | def __init__(self): 122 | self._CommandLine = 'integrator CentralDifference' 123 | 124 | -------------------------------------------------------------------------------- /OpenSeesAPI/Analysis/Numberer.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | This command is used to construct the DOF_Numberer object. The DOF_Numberer object determines the mapping between equation numbers and degrees-of-freedom -- how degrees-of-freedom are numbered. 4 | numberer numbererType? arg1? ... 5 | The type of DOF_Numberer created and the additional arguments required depends on the numbererType? provided in the command. 6 | 7 | The following contain information about numbererType? and the args required for each of the available dof numberer types: 8 | 9 | Plain Numberer 10 | Reverse Cuthill-McKee Numberer 11 | Alternative_Minimum_Degree Numberer 12 | """ 13 | 14 | __author__ = 'Nasser' 15 | 16 | from OpenSeesAPI.OpenSees import OpenSees 17 | 18 | class Plain(OpenSees): 19 | """ 20 | This command is used to construct a Plain degree-of-freedom numbering object to provide the mapping between the degrees-of-freedom at the nodes and the equation numbers. A Plain numberer just takes whatever order the domain gives it nodes and numbers them, this ordering is both dependent on node numbering and size of the model. The command to construct a Plain numberer is a follows: 21 | 22 | numberer Plain 23 | """ 24 | def __init__(self): 25 | self._CommandLine = 'numberer Plain' 26 | 27 | class RCM(OpenSees): 28 | """ 29 | This command is used to construct an RCM degree-of-freedom numbering object to provide the mapping between the degrees-of-freedom at the nodes and the equation numbers. An RCM numberer uses the reverse Cuthill-McKee scheme to order the matrix equations. The command to construct an RCM numberer is a follows: 30 | 31 | numberer RCM 32 | """ 33 | def __init__(self): 34 | self._CommandLine = 'numberer RCM' 35 | 36 | class AMD(OpenSees): 37 | """ 38 | This command is used to construct an AMD degree-of-freedom numbering object to provide the mapping between the degrees-of-freedom at the nodes and the equation numbers. An AMD numberer uses the approximate minimum degree scheme to order the matrix equations. The command to construct an AMD numberer is a follows: 39 | 40 | numberer AMD 41 | """ 42 | def __init__(self): 43 | self._CommandLine = 'numberer AMD' -------------------------------------------------------------------------------- /OpenSeesAPI/Analysis/System.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | This command is used to construct the LinearSOE and LinearSolver objects to store and solve the system of equations in the analysis. 4 | system systemType? arg1? ... 5 | The type of LinearSOE created and the additional arguments required depends on the systemType? provided in the command. 6 | The following contain information about systemType? and the args required for each of the available system types: 7 | BandGeneral SOE 8 | BandSPD SOE 9 | ProfileSPD SOE 10 | SuperLU SOE 11 | UmfPack SOE 12 | FullGeneral 13 | SparseSYM SOE 14 | Mumps 15 | Cusp 16 | """ 17 | 18 | __author__ = 'Nasser' 19 | 20 | from OpenSeesAPI.OpenSees import OpenSees 21 | 22 | class BandGeneral(OpenSees): 23 | """ 24 | This command is used to construct a BandGeneralSOE linear system of equation object. As the name implies, this class is used for matrix systems which have a banded profile. The matrix is stored as shown below in a 1dimensional array of size equal to the bandwidth times the number of unknowns. When a solution is required, the Lapack routines DGBSV and SGBTRS are used. The following command is used to construct such a system: 25 | system BandGeneral 26 | """ 27 | def __init__(self): 28 | self._CommandLine = 'system BandGeneral' 29 | 30 | class BandSPD(OpenSees): 31 | """ 32 | This command is used to construct a BandSPDSOE linear system of equation object. As the name implies, this class is used for symmetric positive definite matrix systems which have a banded profile. The matrix is stored as shown below in a 1 dimensional array of size equal to the (bandwidth/2) times the number of unknowns. When a solution is required, the Lapack routines DPBSV and DPBTRS are used. To following command is used to construct such a system: 33 | system BandSPD 34 | """ 35 | def __init__(self): 36 | self._CommandLine = 'system BandSPD' 37 | 38 | class ProfileSPD(OpenSees): 39 | """ 40 | This command is used to construct a profileSPDSOE linear system of equation object. As the name implies, this class is used for symmetric positive definite matrix systems. The matrix is stored as shown below in a 1 dimensional array with only those values below the first non-zero row in any column being stored. This is sometimes also referred to as a skyline storage scheme. To following command is used to construct such a system: 41 | system ProfileSPD 42 | """ 43 | def __init__(self): 44 | self._CommandLine = 'system ProfileSPD' 45 | 46 | class SuperLU(OpenSees): 47 | """ 48 | This command is used to construct a SparseGEN linear system of equation object. As the name implies, this class is used for sparse matrix systems. The solution of the sparse matrix is carried out using SuperLU. To following command is used to construct such a system: 49 | system SparseGEN 50 | """ 51 | def __init__(self): 52 | self._CommandLine = 'system SparseGEN' 53 | 54 | class UmfPack(OpenSees): 55 | """ 56 | This command is used to construct a sparse system of equations which uses the UmfPack solver. To following command is used to construct such a system: 57 | system UmfPack <-lvalueFact $LVALUE 58 | 59 | (LVALUE*the number of nonzero entries) is the amount of additional memory set aside for fill in during the matrix solution, by default the LVALUE factor is 10. You only need to experiment with this if you get error messages back about LVALUE being too small. 60 | """ 61 | def __init__(self, LValue = None): 62 | self._CommandLine = 'system UmfPack' #Add L Value 63 | 64 | class FullGeneral(OpenSees): 65 | """ 66 | This command is used to construct a Full General linear system of equation object. As the name implies, the class utilizes NO space saving techniques to cut down on the amount of memory used. If the matrix is of size, nxn, then storage for an nxn array is sought from memory when the program runs. When a solution is required, the Lapack routines DGESV and DGETRS are used. The following command is used to construct such a system: 67 | system FullGeneral 68 | """ 69 | def __init__(self): 70 | self._CommandLine = 'system FullGeneral' 71 | 72 | class SparseSYM(OpenSees): 73 | """ 74 | This command is used to construct a sparse symmetric system of equations which uses a row-oriented solution method in the solution phase. To following command is used to construct such a system: 75 | system SparseSYM 76 | """ 77 | def __init__(self): 78 | self._CommandLine = 'system SparseSYM' 79 | 80 | class Mumps(OpenSees): 81 | def __init__(self,Optional=''): 82 | self._Optional = Optional 83 | self._CommandLine = 'system Mumps %s'%self._Optional 84 | 85 | class Cusp(OpenSees): 86 | """ 87 | system CuSP -rTol $RTOL -mInt $MINT -pre $PRE -solver $SOLVER 88 | $RTOL Set the relative tolerance. 89 | $MINT Set the maximum number of iterations. 90 | $PRE Set the preconditioner. can be none, diagonal, and ainv 91 | $SOLVER Set the iterative solver. can be bicg, bicgstab, cg, and gmres. 92 | """ 93 | def __init__(self): 94 | self._CommandLine = 'system CuSP ' 95 | -------------------------------------------------------------------------------- /OpenSeesAPI/Analysis/Test.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | This command is used to construct a ConvergenceTest object. Certain SolutionAlgorithm objects require a ConvergenceTest object to determine if convergence has been achieved at the end of an iteration step. The convergence test is applied to the matrix equation, AX=B stored in the LinearSOE. 4 | test testType? arg1? ... 5 | The type of convergence test created and the additional arguments required depends on the testType? provided in the command. 6 | The following contain information about testType? and the args required for each of the available test types: 7 | test Command Equation 8 | Norm Unbalance Test 9 | Norm Displacement Increment Test 10 | Energy Increment Test 11 | Relative Norm Unbalance Test 12 | Relative Norm Displacement Increment Test 13 | Total Relative Norm Displacement Increment Test 14 | Relative Energy Increment Test 15 | Fixed Number of Iterations 16 | """ 17 | 18 | __author__ = 'Nasser' 19 | 20 | 21 | 22 | from OpenSeesAPI.OpenSees import OpenSees 23 | 24 | class NormUnbalance(OpenSees): 25 | """ 26 | test NormUnbalance $tol $iter <$pFlag> <$nType> 27 | $tol the tolerance criteria used to check for convergence 28 | $iter the max number of iterations to check before returning failure condition 29 | $pFlag optional print flag, default is 0. valid options: 30 | 0 print nothing 31 | 1 print information on norms each time test() is invoked 32 | 2 print information on norms and number of iterations at end of successfull test 33 | 4 at each step it will print the norms and also the ?U and R(U) vectors. 34 | 5 if it fails to converge at end of $numIter it will print an error message BUT RETURN A SUCEESSFULL test 35 | $nType optional type of norm, default is 2. (0 = max-norm, 1 = 1-norm, 2 = 2-norm, ...) 36 | """ 37 | def __init__(self, Tolerance, MaxIterations, PrintFlag=None, nType=None): 38 | self._Tolerance = Tolerance 39 | self._MaxIterations = MaxIterations 40 | self._PrintFlag = PrintFlag 41 | self._nType =nType 42 | if self._PrintFlag != None: 43 | self._Optional = '%d'%(PrintFlag) 44 | elif self._nType != None: 45 | self._Optional = '%d %d'%(PrintFlag,nType) 46 | else: 47 | self._Optional = '' 48 | self._CommandLine = 'test NormUnbalance %e %d %s'%(Tolerance,MaxIterations,self._Optional) 49 | 50 | class NormDispIncr(OpenSees): 51 | """ 52 | This command is used to construct a convergence test which uses the norm of the left hand side solution vector of the matrix equation to determine if convergence has been reached. What the solution vector of the matrix equation is depends on integrator and constraint handler chosen. Usually, though not always, it is equal to the displacement increments that are to be applied to the model. The command to create a NormDispIncr test is the following: 53 | test NormDispIncr $tol $iter <$pFlag> <$nType> 54 | 55 | $tol the tolerance criteria used to check for convergence 56 | $iter the max number of iterations to check before returning failure condition 57 | $pFlag optional print flag, default is 0. valid options: 58 | 0 print nothing 59 | 1 print information on norms each time test() is invoked 60 | 2 print information on norms and number of iterations at end of successfull test 61 | 4 at each step it will print the norms and also the ?U and R(U) vectors. 62 | 5 if it fails to converge at end of $numIter it will print an error message BUT RETURN A SUCEESSFULL test 63 | $nType optional type of norm, default is 2. (0 = max-norm, 1 = 1-norm, 2 = 2-norm, ...) 64 | """ 65 | def __init__(self, Tolerance, MaxIterations, pFlag=0, nType=2): 66 | self._Tolerance = Tolerance 67 | self._MaxIterations = MaxIterations 68 | self._pFlag = pFlag 69 | self._nType = nType 70 | self._CommandLine = 'test NormDispIncr %e %d %d %d'%(self._Tolerance,self._MaxIterations, self._pFlag, self._nType) 71 | 72 | class EnergyIncr(OpenSees): 73 | """ 74 | test EnergyIncr $tol $iter <$pFlag> <$nType> 75 | 76 | $tol the tolerance criteria used to check for convergence 77 | $iter the max number of iterations to check before returning failure condition 78 | $pFlag optional print flag, default is 0. valid options: 79 | 0 print nothing 80 | 1 print information on norms each time test() is invoked 81 | 2 print information on norms and number of iterations at end of successfull test 82 | 4 at each step it will print the norms and also the ?U and R(U) vectors. 83 | 5 if it fails to converge at end of $numIter it will print an error message BUT RETURN A SUCEESSFULL test 84 | $nType optional type of norm, default is 2. (0 = max-norm, 1 = 1-norm, 2 = 2-norm, ...) 85 | """ 86 | def __init__(self, Tolerance, MaxIterations, pFlag = 0 , nType=2): 87 | self._Tolerance = Tolerance 88 | self._MaxIterations = MaxIterations 89 | self._CommandLine = 'test EnergyIncr %e %d %d %d'%(Tolerance,MaxIterations,pFlag,nType) 90 | 91 | class RelativeNormUnbalance(OpenSees): 92 | def __init__(self, Tolerance, MaxIterations): 93 | self._Tolerance = Tolerance 94 | self._MaxIterations = MaxIterations 95 | self._CommandLine = 'test RelativeNormUnbalance %e %d'%(Tolerance,MaxIterations) 96 | 97 | class RelativeNormDispIncr(OpenSees): 98 | def __init__(self, Tolerance, MaxIterations): 99 | self._Tolerance = Tolerance 100 | self._MaxIterations = MaxIterations 101 | self._CommandLine = 'test RelativeNormDispIncr %e %d'%(Tolerance,MaxIterations) 102 | 103 | class RelativeEnergyIncr(OpenSees): 104 | def __init__(self, Tolerance, MaxIterations): 105 | self._Tolerance = Tolerance 106 | self._MaxIterations = MaxIterations 107 | self._CommandLine = 'test RelativeEnergyIncr %e d'%(Tolerance,MaxIterations) -------------------------------------------------------------------------------- /OpenSeesAPI/Analysis/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Nasser' 2 | 3 | # Import Folder with Several Classes 4 | from OpenSeesAPI.Analysis import Algorithm 5 | from OpenSeesAPI.Analysis import Analysis 6 | from OpenSeesAPI.Analysis import Analyze 7 | from OpenSeesAPI.Analysis import Constraints 8 | from OpenSeesAPI.Analysis import Integrator 9 | from OpenSeesAPI.Analysis import Numberer 10 | from OpenSeesAPI.Analysis import System 11 | from OpenSeesAPI.Analysis import Test 12 | 13 | # Import One Class Files 14 | from OpenSeesAPI.Analysis.Eigen import Eigen 15 | -------------------------------------------------------------------------------- /OpenSeesAPI/Database.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | 4 | """ 5 | 6 | __author__ = 'Nasser' 7 | 8 | # This Stores All The OpenSees Instances 9 | 10 | import OpenSeesAPI 11 | 12 | class Collector(object): 13 | ''' This Declares Tcl File Headers 14 | Naming Convention for Element ID: 15 | Nodes: 1ZZXXXX 16 | SubNodes: 2ZZXXXX 17 | OtherNodes: 3ZZXXXX 18 | Reserved: 4ZZXXXX 19 | Columns: 5ZZXXXX 20 | Beams: 6ZZXXXX 21 | Braces: 7ZZXXXX 22 | Planes: 8ZZXXXX 23 | ZeroLength/Other: 9ZZXXXX 24 | 25 | GroupID is Story Number 26 | ''' 27 | 28 | def __init__(self, OpenSeesCommand, FileLocation, TCLFileName): 29 | """ 30 | 31 | :param OpenSeesCommand: Name of OpenSees Exeutable File 32 | :param FileLocation: Folder location of where you would like the analysis to be 33 | :param TCLFileName: Analysis File Name 34 | :return: OpenSeesAPI Collector Object. This is Where all the OSAPI objects are stored prior to running analysis 35 | 36 | """ 37 | 38 | self._Executable = OpenSeesAPI.Executable(OpenSeesCommand, FileLocation, TCLFileName) 39 | self._Object = [] 40 | self._Nodes = [] 41 | self._Elements = [] 42 | self._Materials = [] 43 | self._Sections = [] 44 | self._Constraints = [] 45 | self._Quadrilaterals = [] 46 | self._ElementIds = {} 47 | self._NodeIds = {} 48 | self._MaterialIds = {} 49 | self._SectionIds = {} 50 | self._Mass = [] 51 | 52 | @property 53 | def Executable(self): 54 | return self._Executable 55 | 56 | def AddObject(self, Obj): 57 | self._Object.append(Obj) 58 | self._Executable.AddCommand(Obj.CommandLine) 59 | return Obj 60 | 61 | def AddNode(self, Node): 62 | self._Nodes.append(Node) 63 | return Node 64 | 65 | def AddElement(self, Element): 66 | self._Elements.append(Element) 67 | return Element 68 | 69 | def AddMaterial(self, Material): 70 | self._Materials.append(Material) 71 | return Material 72 | 73 | def AddSection(self, Section): 74 | self._Sections.append(Section) 75 | return Section 76 | 77 | def AddMass(self, Mass): 78 | self._Mass.append(Mass) 79 | return Mass 80 | 81 | def AddConstraint(self, Constraint): 82 | self._Constraints.append(Constraint) 83 | return Constraint 84 | 85 | def AddQuadrilateral(self, Quarilateral): 86 | self._Quadrilaterals.append(Quarilateral) 87 | return Quarilateral 88 | 89 | def GetFreeNodeId(self, NodeType, GroupId): 90 | temp = '%d%d'%(NodeType, GroupId) 91 | if temp in self._NodeIds: 92 | self._NodeIds[temp] += 1 93 | else: 94 | self._NodeIds[temp] = 1 95 | id = '%4.0f'%self._NodeIds[temp] 96 | id = id.replace(' ','0') 97 | return int('%s%s'%(temp,id)) 98 | 99 | def GetFreeSectionId(self, SectionType, GroupId): 100 | temp = '%d%d'%(SectionType, GroupId) 101 | if temp in self._SectionIds: 102 | self._SectionIds[temp] += 1 103 | else: 104 | self._SectionIds[temp] = 1 105 | id = '%4.0f'%self._SectionIds[temp] 106 | id = id.replace(' ','0') 107 | return int('%s%s'%(temp,id)) 108 | 109 | def GetFreeElementId(self, ElementType, GroupId): 110 | temp = '%d%d'%(ElementType, GroupId) 111 | if temp in self._ElementIds: 112 | self._ElementIds[temp] += 1 113 | else: 114 | self._ElementIds[temp] = 1 115 | id = '%4.0f'%self._ElementIds[temp] 116 | id = id.replace(' ','0') 117 | return int('%s%s'%(temp,id)) 118 | 119 | def GetFreeMaterialId(self, MaterialType, GroupId): 120 | temp = '%d%d'%(MaterialType, GroupId) 121 | if temp in self._MaterialIds: 122 | self._MaterialIds[temp] += 1 123 | else: 124 | self._MaterialIds[temp] = 1 125 | id = '%4.0f'%self._MaterialIds[temp] 126 | id = id.replace(' ','0') 127 | return int('%s%s'%(temp,id)) 128 | 129 | def CreateNode(self, X, Y, Z=None, NodeType=1, GridX=None, GridY=None, GridZ=None, GroupId=1,_Notes=None): 130 | id = self.GetFreeNodeId(NodeType, GroupId) 131 | Node = OpenSeesAPI.Model.Node.Node(id, X, Y, Z, GridX=GridX, GridY=GridY, GridZ=GridZ, NodeType=NodeType,_Notes=_Notes) 132 | self._Nodes.append(Node) 133 | return Node 134 | 135 | def AssignUsedNodes(self): 136 | # setting nodes that are used by the Elements 137 | for object in set(self._Elements): 138 | object._NodeI.__setattr__('Used', True) 139 | object._NodeJ.__setattr__('Used', True) 140 | if hasattr(object,'NodeK'): 141 | object._NodeK.__setattr__('Used', True) 142 | if hasattr(object,'NodeL'): 143 | object._NodeL.__setattr__('Used', True) 144 | if hasattr(object,'NodeM'): 145 | object._NodeM.__setattr__('Used', True) 146 | 147 | for object in set(self._Quadrilaterals): 148 | object._NodeI.__setattr__('Used', True) 149 | object._NodeJ.__setattr__('Used', True) 150 | if hasattr(object,'_NodeK'): 151 | object._NodeK.__setattr__('Used', True) 152 | if hasattr(object,'_NodeL'): 153 | object._NodeL.__setattr__('Used', True) 154 | if hasattr(object,'_NodeM'): 155 | object._NodeM.__setattr__('Used', True) 156 | 157 | 158 | def WriteModel(self): 159 | # setting nodes that are used by the Elements 160 | for object in set(self._Elements): 161 | object._NodeI.__setattr__('Used', True) 162 | object._NodeJ.__setattr__('Used', True) 163 | if hasattr(object,'NodeK'): 164 | object._NodeK.__setattr__('Used', True) 165 | if hasattr(object,'NodeL'): 166 | object._NodeL.__setattr__('Used', True) 167 | if hasattr(object,'NodeM'): 168 | object._NodeM.__setattr__('Used', True) 169 | 170 | # Writing Nodes to File 171 | self.AddObject(OpenSeesAPI.TCL.CodeTitle('Defining Nodes')) 172 | for obj in self._Nodes: 173 | if hasattr(obj, 'Used'): 174 | if obj.Used: 175 | self.Executable.AddCommand(obj.CommandLine) 176 | 177 | self.AddObject(OpenSeesAPI.TCL.CodeTitle('Defining Node Mass')) 178 | for obj in self._Mass: 179 | self.Executable.AddCommand(obj.CommandLine) 180 | 181 | self.AddObject(OpenSeesAPI.TCL.CodeTitle('Defining Materials')) 182 | for obj in self._Materials: 183 | self.Executable.AddCommand(obj.CommandLine) 184 | 185 | # Write Sections from OpenSees Collector 186 | self.AddObject(OpenSeesAPI.TCL.CodeTitle('Defining Sections')) 187 | for obj in self._Sections: 188 | self.Executable.AddCommand(obj.CommandLine) 189 | 190 | # Write Elements from OpenSees Collector 191 | self.AddObject(OpenSeesAPI.TCL.CodeTitle('Defining Elements')) 192 | for obj in self._Elements: 193 | self.Executable.AddCommand(obj.CommandLine) 194 | 195 | # Write Shells from OpenSees Collector 196 | self.AddObject(OpenSeesAPI.TCL.CodeTitle('Defining Shells')) 197 | for obj in self._Quadrilaterals: 198 | self.Executable.AddCommand(obj.CommandLine) 199 | 200 | # Write Restraints/Constraints from OpenSees Collector 201 | self.AddObject(OpenSeesAPI.TCL.CodeTitle('Defining Restraints/Constraints')) 202 | for obj in self._Constraints: 203 | self.Executable.AddCommand(obj.CommandLine) 204 | 205 | #Methods 206 | def GetNodesByYCoordinate(self, YCoordinate, NodeType=1): 207 | return list(filter(lambda x: x.Y==YCoordinate and x.NodeType==NodeType, self._Nodes)) 208 | 209 | def GetNodesByZCoordinate(self, ZCoordinate, NodeType=1): 210 | return list(filter(lambda x: x.Z==ZCoordinate and x.NodeType==NodeType, self._Nodes)) 211 | 212 | def GetNodesByGrid(self, GridX, GridY, GridZ=None, NodeType=1): 213 | if GridZ == None: 214 | return list(filter(lambda x: x.GridX==GridX and x.GridY==GridY and x.NodeType==NodeType, self._Nodes)) 215 | else: 216 | return list(filter(lambda x: x.GridX==GridX and x.GridY==GridY and x.GridZ==GridZ and x.NodeType==NodeType, self._Nodes)) 217 | 218 | def GetNodesByYGrid(self, GridY, NodeType=1): 219 | return list(filter(lambda x: x.GridY==GridY and x.NodeType==NodeType, self._Nodes)) 220 | 221 | def GetNodesByZGrid(self, GridZ, NodeType=1): 222 | return list(filter(lambda x: x.GridZ==GridZ and x.NodeType==NodeType, self._Nodes)) 223 | 224 | def GetNode(self, id): 225 | return list(filter(lambda x: x.id == id, self._Nodes))[0] 226 | 227 | def GetNodeByCoordinate(self,X, Y, Z, NodeType=1): 228 | return list(filter(lambda x: x.X == X and x.Y == Y and x.Z == Z and x.NodeType == NodeType, self._Nodes)) 229 | 230 | def GetNodeByCoordinateWithTolerance(self,X, Y, Z, NodeType=1, DecimalPoint = 2): 231 | DP = DecimalPoint 232 | return list(filter(lambda x: round(x.X,DP) == round(X,DP) and round(x.Y,DP) == round(Y,DP) and round(x.Z,DP) == round(Z,DP) and x.NodeType == NodeType, self._Nodes)) -------------------------------------------------------------------------------- /OpenSeesAPI/Helpers/Materials.py: -------------------------------------------------------------------------------- 1 | """ 2 | This helper is used to make material classes, for example if you have using a 3 | """ 4 | 5 | __author__ = 'XXXX' 6 | 7 | import OpenSeesAPI -------------------------------------------------------------------------------- /OpenSeesAPI/Helpers/Sections.py: -------------------------------------------------------------------------------- 1 | """ 2 | This helper is used to create fiber sections. for e.g. if you have a RC column with reinforcement, this could be used to make it. 3 | """ 4 | 5 | __author__ = 'XXXX' 6 | 7 | import OpenSeesAPI -------------------------------------------------------------------------------- /OpenSeesAPI/Helpers/SolutionAlgorithms.py: -------------------------------------------------------------------------------- 1 | """ 2 | This helper is used to create the following OpenSees TCL Commands: 3 | This command is used to build a Solution Method object that determines how the program executes the step evaluation and 4 | handles non-convergence (i.e. ok not 0) 5 | """ 6 | 7 | __author__ = 'Stephens/Thonstad, Modified by Marafi' 8 | 9 | import OpenSeesAPI 10 | 11 | def BasicTimeHistory(OData, Dt, Steps): 12 | """ 13 | 14 | :param OData: osapi database object 15 | :param Dt: time step 16 | :param Steps: number of steps 17 | :return: adds the solution algorithm to the database file 18 | """ 19 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok 0')) 20 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set Nsteps %d'%Steps)) 21 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set step 0')) 22 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('while {$ok == 0 & $step < [expr $Nsteps +1]} {')) 23 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze 1 %f]'%Dt)) 24 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Running Time History Step: $step out of %d"'%Steps)) 25 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set step [expr $step+1]')) 26 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('}')) 27 | 28 | def GravityAnalysis(OData, Steps): 29 | """ 30 | 31 | :param OData: osapi database object 32 | :param Steps: number of steps 33 | :return: adds the solution algorithm to the database file 34 | """ 35 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('analyze %d'%Steps)) 36 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('loadConst - time 0.0')) 37 | 38 | def ChangeAlgorithm(OData, Dt, Steps): 39 | """ 40 | 41 | :param OData: osapi database object 42 | :param Dt: time steps 43 | :param Steps: number of steps 44 | :return: adds the solution algorithm to the database file 45 | """ 46 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok 0')) 47 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('while{$ok == 0} {')) 48 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]'%(Steps,Dt))) 49 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t if {$ok != 0} {')) 50 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Trying Newton Line Search ... "')) 51 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t' + OpenSeesAPI.Analysis.Algorithm.NewtonLineSearch(Tolerance=0.8).CommandLine + '')) 52 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]'%(Steps,Dt))) 53 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t }\n')) 54 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t if {$ok != 0} {')) 55 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Trying Newton with Initial Tangent ... "')) 56 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t' + OpenSeesAPI.Analysis.Newton(Initial=True).CommandLine + '')) 57 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]'%(Steps,Dt))) 58 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t }\n')) 59 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t if {$ok != 0} {')) 60 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Trying Broyden ... "')) 61 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t' + OpenSeesAPI.Analysis.Broyden(8).CommandLine + '')) 62 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]\n'%(Steps,Dt))) 63 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t }\n')) 64 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t if {$ok != 0} {')) 65 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Trying KrylovNewton ... "')) 66 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t' + OpenSeesAPI.Analysis.KrylovNewton().CommandLine + '')) 67 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]'%(Steps,Dt))) 68 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t }\n')) 69 | 70 | def DisplacementTestStep(OData, Dt, Tol, Steps,): 71 | """ 72 | 73 | :param OData: osapi database object 74 | :param Dt: time step 75 | :param Tol: tolerance 76 | :param Steps: number of steps 77 | :return: adds the solution algorithm to the database file 78 | """ 79 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok 0')) 80 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('while{$ok == 0} {')) 81 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t if {$ok != 0} {')) 82 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Trying Lower Dt: %f and Tol: %f ... "'%(Dt,Tol))) 83 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t' + OpenSeesAPI.Analysis.Test.NormDispIncr(Tol,1000,0).CommandLine + '')) 84 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]'%(Steps,Dt))) 85 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t }\n')) 86 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t if {$ok != 0} {')) 87 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Trying Lower Dt: %f and Tol: %f ... "'%(Dt*0.1,Tol))) 88 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t' + OpenSeesAPI.Analysis.Test.NormDispIncr(Tol,1000,0).CommandLine + '')) 89 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]'%(Steps,0.1*Dt))) 90 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t }\n')) 91 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t if {$ok != 0} {')) 92 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Trying Lower Dt: %f and Tol: %f ... "'%(Dt*0.01,Tol))) 93 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t' + OpenSeesAPI.Analysis.Test.NormDispIncr(Tol,1000,0).CommandLine + '')) 94 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]'%(Steps,0.01*Dt))) 95 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t }\n')) 96 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t if {$ok != 0} {\n')) 97 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Trying Lower Dt: %f and Tol: %f ... "'%(Dt*0.001,Tol))) 98 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t' + OpenSeesAPI.Analysis.Test.NormDispIncr(Tol,1000,0).CommandLine + '')) 99 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]'%(Steps,0.001*Dt))) 100 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t }\n')) 101 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t if {$ok != 0} {')) 102 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Trying Lower Dt: %f and Tol: %f ... "'%(Dt*0.0001,Tol))) 103 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t' + OpenSeesAPI.Analysis.Test.NormDispIncr(Tol,1000,0).CommandLine + '')) 104 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]'%(Steps,0.0001*Dt))) 105 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t }\n')) 106 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t if {$ok != 0} {')) 107 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts "Trying Lower Dt: %f and Tol: %f ... "'%(Dt*0.0000001,Tol))) 108 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t' + OpenSeesAPI.Analysis.Test.NormDispIncr(Tol,1000,0).CommandLine + '')) 109 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze %d %f ]\n'%(Steps,0.0000001*Dt))) 110 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t }')) 111 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('}')) 112 | 113 | def TestComparison(OData, DisplacmentFileName, controlNodeID, DOF,): 114 | """ 115 | TestComparison(Dt,Tol,DisplacementFileName,controlNodeID,DOF) 116 | Finds the solution of the system at specific diplacement steps defined in DisplacementFileName (.txt file) at 117 | the control node (controlNodeID) in the specified degree of freedom. 118 | :param OData: osapi database object 119 | :param DisplacmentFileName: displacement file name 120 | :param controlNodeID: control node id 121 | :param DOF: degree of freedom to push 122 | :return: adds the solution algorithm to the database file 123 | """ 124 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set fid [open %s r]'%DisplacmentFileName)) 125 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set def [read $fid]')) 126 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set numSteps [llength $def]')) 127 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok 0 ')) 128 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set stepNum 0')) 129 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('while {$ok == 0 && $stepNum < [expr $numSteps-1]} { ')) 130 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set U1 [lindex $def $stepNum]')) 131 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t puts $U1')) 132 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set U2 [lindex $def $stepNum+1]')) 133 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set dU [expr $U2-$U1]')) 134 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t integrator DisplacementControl %s %d $dU 1 $dU $dU'%(controlNodeID,DOF))) 135 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t set ok [analyze 1]')) 136 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('\t incr stepNum')) 137 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('}')) -------------------------------------------------------------------------------- /OpenSeesAPI/Helpers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nassermarafi/OpenSeesAPI/697167cf4c73c4e094c9896d76cfca0eeeb97f09/OpenSeesAPI/Helpers/__init__.py -------------------------------------------------------------------------------- /OpenSeesAPI/Misc.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | List of Available Commands 4 | eleResponse Command 5 | getTime Command 6 | getEleTags Command 7 | getNodeTags 8 | loadConst 9 | nodeCoord 10 | nodeDisp 11 | nodeVel 12 | nodeAccel 13 | nodeEigenvector 14 | nodeBounds 15 | print 16 | printA 17 | remove 18 | reset 19 | setTime 20 | setMaxOpenFiles 21 | testIter 22 | testNorms 23 | wipe 24 | wipeAnalysis 25 | exit Command 26 | """ 27 | 28 | __author__ = 'Nasser Marafi' 29 | 30 | from OpenSeesAPI.OpenSees import OpenSees 31 | 32 | class Wipe(OpenSees): 33 | def __init__(self): 34 | self._CommandLine = 'wipe all;' 35 | -------------------------------------------------------------------------------- /OpenSeesAPI/Model/BasicBuilder.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | model BasicBuilder 4 | """ 5 | 6 | __author__ = 'Nasser Marafi' 7 | 8 | from OpenSeesAPI.OpenSees import OpenSees 9 | 10 | class BasicBuilder(OpenSees): 11 | """ 12 | This command is used to define spatial dimension of model and number of degrees-of-freedom at nodes. Once issued additional commands are added to interpreter. 13 | model BasicBuilder -ndm $ndm <-ndf $ndf> 14 | $ndm spatial dimension of problem (1,2, or 3) 15 | $ndf number of degrees of freedom at node (optional) 16 | default value depends on value of ndm: 17 | ndm=1 -> ndf=1 18 | ndm=2 -> ndf=3 19 | ndm=3 -> ndf=6 20 | """ 21 | def __init__(self, NoDim, NoDOF): 22 | self._NoDim = NoDim 23 | self._NoDOF = NoDOF 24 | self._CommandLine = 'model BasicBuilder -ndm %d -ndf %d;'%(self._NoDim, self._NoDOF) -------------------------------------------------------------------------------- /OpenSeesAPI/Model/Constraint.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | 4 | SP_Constraint (single-point constraint), which prescribe the movement (typically 0) of a single dof at a node. There are a number of commands for creating single-point coonstraints: 5 | fix 6 | fixX 7 | fixY 8 | fixZ 9 | 10 | MP_Constraint (multi-point constraint), which prescribe that the movement of certain dof at one node are defined by the movement of certain dof at another node. There again are a number of commands for defining multi-point constraints. 11 | equalDOF 12 | rigidDiaphragm 13 | rigidLink 14 | """ 15 | 16 | __author__ = 'Nasser Marafi' 17 | 18 | from OpenSeesAPI.OpenSees import OpenSees 19 | 20 | class Fix(OpenSees): 21 | """ 22 | fix $nodeTag (ndf $constrValues) 23 | $nodeTag integer tag identifying the node to be constrained 24 | $constrValues ndf constraint values (0 or 1) corresponding to the ndf degrees-of-freedom. 25 | 0 unconstrained (or free) 26 | 1 constrained (or fixed) 27 | """ 28 | def __init__(self, Node, DOFList, **kwargs): 29 | self._Node = Node 30 | self._DOFList = DOFList 31 | self._CommandLine = 'fix %d %s'%(Node.id, ''.join([' %d'%x for x in DOFList])) 32 | self.__dict__.update(kwargs) 33 | 34 | class EqualDOF(OpenSees): 35 | """ 36 | equalDOF $rNodeTag $cNodeTag $dof1 $dof2 ... 37 | $rNodeTag integer tag identifying the retained, or master node (rNode) 38 | $cNodeTag integer tag identifying the constrained, or slave node (cNode) 39 | $dof1 $dof2 ... nodal degrees-of-freedom that are constrained at the cNode to be the same as those at the rNode 40 | Valid range is from 1 through ndf, the number of nodal degrees-of-freedom. 41 | """ 42 | def __init__(self, MasterNode, SlaveNode, DOFList, **kwargs): 43 | self._MasterNode = MasterNode 44 | self._SlaveNode = SlaveNode 45 | self._DOFList = DOFList 46 | self.__dict__.update(kwargs) 47 | 48 | self._CommandLine = 'equalDOF %d %d %s'%(self._MasterNode.id, self._SlaveNode.id, ''.join([' %d'%x for x in self._DOFList])) 49 | 50 | class RigidDiaphragm(OpenSees): 51 | """ 52 | rigidDiaphragm $perpDirn $masterNodeTag $slaveNodeTag1 $slaveNodeTag2 ... 53 | $perpDirn direction perpendicular to the rigid plane (i.e. direction 3 corresponds to the 1-2 plane) 54 | $masterNodeTag integer tag identifying the master node 55 | $slaveNodeTag1 $slaveNodeTag2 ... integar tags identifying the slave nodes 56 | """ 57 | def __init__(self, perpDOF, MasterNode, SlaveNodeList, **kwargs): 58 | self._perpDOF = perpDOF 59 | self._MasterNode = MasterNode 60 | self._SlaveNodeList = SlaveNodeList 61 | self.__dict__.update(kwargs) 62 | 63 | self._CommandLine = 'rigidDiaphragm %d %d %s'%(self._perpDOF, self._MasterNode.id, ''.join([' %d'%x.id for x in self._SlaveNodeList])) 64 | 65 | class RigidLink(OpenSees): 66 | """ 67 | rigidLink $type $masterNodeTag $slaveNodeTag 68 | $type string-based argument for rigid-link type: 69 | bar only the translational degree-of-freedom will be constrained to be exactly the same as those at the master node 70 | beam both the translational and rotational degrees of freedom are constrained. 71 | $masterNodeTag integer tag identifying the master node 72 | $slaveNodeTag integer tag identifying the slave node 73 | """ 74 | def __init__(self, Type, MasterNode, SlaveNode, **kwargs): 75 | self._Type = Type 76 | self._MasterNode = MasterNode 77 | self._SlaveNode = SlaveNode 78 | self.__dict__.update(kwargs) 79 | 80 | self._CommandLine = 'rigidLink %s %d %d'%(self._Type, self._MasterNode.id, self._SlaveNode.id) 81 | -------------------------------------------------------------------------------- /OpenSeesAPI/Model/Element/GeomTransf.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | The following contain information about transfType? and the args required for each of the available geometric transformation types: 4 | Linear Transformation 5 | PDelta Transformation 6 | Corotational Transformation 7 | """ 8 | 9 | __author__ = 'Nasser' 10 | 11 | from OpenSeesAPI.OpenSees import OpenSees 12 | 13 | class Linear(OpenSees): 14 | """ 15 | For a two-dimensional problem: 16 | geomTransf Linear $transfTag <-jntOffset $dXi $dYi $dXj $dYj> 17 | For a three-dimensional problem: 18 | geomTransf Linear $transfTag $vecxzX $vecxzY $vecxzZ <-jntOffset $dXi $dYi $dZi $dXj $dYj $dZj> 19 | 20 | $transfTag integer tag identifying transformation 21 | $vecxzX $vecxzY $vecxzZ X, Y, and Z components of vecxz, the vector used to define the local x-z plane of the local-coordinate system. The local y-axis is defined by taking the cross product of the vecxz vector and the x-axis. 22 | These components are specified in the global-coordinate system X,Y,Z and define a vector that is in a plane parallel to the x-z plane of the local-coordinate system. 23 | These items need to be specified for the three-dimensional problem. 24 | $dXi $dYi $dZi joint offset values -- offsets specified with respect to the global coordinate system for element-end node i (the number of arguments depends on the dimensions of the current model). The offset vector is oriented from node i to node j as shown in a figure below. (optional) 25 | $dXj $dYj $dZj joint offset values -- offsets specified with respect to the global coordinate system for element-end node j (the number of arguments depends on the dimensions of the current model). The offset vector is oriented from node j to node i as shown in a figure below. (optional) 26 | 27 | A refresher on Euclidean Geometry and Coordinate Systems: 28 | A single vector may be defined by two points. It has length, direction, and location in space. When this vector is used to define a coordinate axis, only its direction is important. Now any 2 vectors, Vr and Vs, not parallel, define a plane that is parallel to them both. The cross-product of these vectors define a third vector, Vt, that is perpendicular to both Vr and Vs and hence normal to the plane: Vt = Vr X Vs. 29 | 30 | The element coordinate system is specified as follows: 31 | The x-axis is a vector given by the two element nodes; The vector vecxz is a vector the user specifies that must not be parallel to the x-axis. The x-axis along with the vecxz Vector define the xz plane. The local y-axis is defined by taking the cross product of the x-axis vector and the vecxz vector (Vy = Vxz X Vx). The local z-axis is then found simply by taking the cross product of the y-axis and x-axis vectors (Vz = Vx X Vy). The section is attached to the element such that the y-z coordinate system used to specify the section corresponds to the y-z axes of the element. 32 | """ 33 | def __init__(self, id, VectorX=None, VectorY=None, VectorZ=None, **kwargs): 34 | self._id = id 35 | self._VectorX = VectorX 36 | self._VectorY = VectorY 37 | self._VectorZ = VectorZ 38 | 39 | self.__dict__.update(kwargs) 40 | 41 | if self._VectorX == None: 42 | self._CommandLine = 'geomTransf Linear %d'%(self.id) 43 | else: 44 | self._CommandLine = 'geomTransf Linear %d %d %d %d'%(self.id, self._VectorX, self._VectorY, self._VectorZ) 45 | 46 | 47 | class PDelta(OpenSees): 48 | """ 49 | For a two-dimensional problem: 50 | geomTransf PDelta $transfTag <-jntOffset $dXi $dYi $dXj $dYj> 51 | For a three-dimensional problem: 52 | geomTransf PDelta $transfTag $vecxzX $vecxzY $vecxzZ <-jntOffset $dXi $dYi $dZi $dXj $dYj $dZj> 53 | 54 | $transfTag integer tag identifying transformation 55 | $vecxzX $vecxzY $vecxzZ X, Y, and Z components of vecxz, the vector used to define the local x-z plane of the local-coordinate system. The local y-axis is defined by taking the cross product of the vecxz vector and the x-axis. 56 | These components are specified in the global-coordinate system X,Y,Z and define a vector that is in a plane parallel to the x-z plane of the local-coordinate system. 57 | These items need to be specified for the three-dimensional problem. 58 | $dXi $dYi $dZi joint offset values -- offsets specified with respect to the global coordinate system for element-end node i (the number of arguments depends on the dimensions of the current model). The offset vector is oriented from node i to node j as shown in a figure below. (optional) 59 | $dXj $dYj $dZj joint offset values -- offsets specified with respect to the global coordinate system for element-end node j (the number of arguments depends on the dimensions of the current model). The offset vector is oriented from node j to node i as shown in a figure below. (optional) 60 | """ 61 | def __init__(self, id, VectorX=None, VectorY=None, VectorZ=None, jinOffset = None, **kwargs): 62 | self._id = id 63 | self._VectorX = VectorX 64 | self._VectorY = VectorY 65 | self._VectorZ = VectorZ 66 | self._jinOffset = jinOffset 67 | 68 | self.__dict__.update(kwargs) 69 | 70 | if self._VectorX == None: 71 | self._CommandLine = 'geomTransf PDelta %d'%(self.id) 72 | else: 73 | if self._jinOffset == None: 74 | self._CommandLine = 'geomTransf PDelta %d %d %d %d'%( 75 | self.id, self._VectorX, self._VectorY, self._VectorZ) 76 | else: 77 | self._CommandLine = 'geomTransf PDelta %d %d %d %d -jntOffset %s' % ( 78 | self.id, self._VectorX, self._VectorY, self._VectorZ, ''.join([' %f'%x for x in self._jinOffset])) 79 | 80 | 81 | class Corotational(OpenSees): 82 | """ 83 | For a two-dimensional problem: 84 | geomTransf Corotational $transfTag <-jntOffset $dXi $dYi $dXj $dYj> 85 | For a three-dimensional problem: 86 | geomTransf Corotational $transfTag $vecxzX $vecxzY $vecxzZ 87 | PDelta 88 | $transfTag integer tag identifying transformation 89 | $vecxzX $vecxzY $vecxzZ X, Y, and Z components of vecxz, the vector used to define the local x-z plane of the local-coordinate system. The local y-axis is defined by taking the cross product of the vecxz vector and the x-axis. 90 | These components are specified in the global-coordinate system X,Y,Z and define a vector that is in a plane parallel to the x-z plane of the local-coordinate system. 91 | These items need to be specified for the three-dimensional problem. 92 | $dXi $dYi joint offset values -- absolute offsets specified with respect to the global coordinate system for element-end node i (optional) 93 | $dXj $dYj joint offset values -- absolute offsets specified with respect to the global coordinate system for element-end node j (optional) 94 | 95 | The element coordinate system is specified as follows: 96 | The x-axis is the axis connecting the two element nodes; the y- and z-axes are then defined using a vector that lies on a plane parallel to the local x-z plane -- vecxz. The local y-axis is defined by taking the cross product of the vecxz vector and the x-axis. The z-axis by taking cross product of x and new y. The section is attached to the element such that the y-z coordinate system used to specify the section corresponds to the y-z axes of the element. 97 | """ 98 | def __init__(self, id, VectorX=None, VectorY=None, VectorZ=None, **kwargs): 99 | self._id = id 100 | self._VectorX = VectorX 101 | self._VectorY = VectorY 102 | self._VectorZ = VectorZ 103 | 104 | self.__dict__.update(kwargs) 105 | 106 | if self._VectorX == None: 107 | self._CommandLine = 'geomTransf Corotational %d'%(self.id) 108 | else: 109 | self._CommandLine = 'geomTransf Corotational %d %d %d %d'%(self.id, self._VectorX, self._VectorY, self._VectorZ) -------------------------------------------------------------------------------- /OpenSeesAPI/Model/Element/Material/NDMaterial.py: -------------------------------------------------------------------------------- 1 | """ 2 | Elastic Isotropic Material 3 | Elastic Orthotropic Material 4 | J2 Plasticity Material 5 | Drucker Prager Material 6 | Concrete Damage Model 7 | Plane Stress Material 8 | Plane Strain Material 9 | Multi Axial Cyclic Plasticity 10 | Bounding Cam Clay 11 | Plate Fiber Material 12 | Plane Stress Concrete Materials 13 | Tsinghua Sand Models 14 | CycLiqCP Material (Cyclic ElasticPlasticity) 15 | CycLiqCPSP Material 16 | Manzari Dafalias Material 17 | Materials for Modeling Concrete Walls 18 | PlaneStressUserMaterial 19 | PlateFromPlaneStress 20 | PlateRebar 21 | LayeredShell 22 | Contact Materials for 2D and 3D 23 | ContactMaterial2D 24 | ContactMaterial3D 25 | Wrapper material for Initial State Analysis 26 | InitialStateAnalysisWrapper 27 | UC San Diego soil models (Linear/Nonlinear, dry/drained/undrained soil response under general 2D/3D static/cyclic loading conditions (please visit UCSD for examples) 28 | PressureIndependMultiYield Material 29 | PressureDependMultiYield Material 30 | PressureDependMultiYield02 Material 31 | UC San Diego Saturated Undrained soil 32 | FluidSolidPorousMaterial 33 | UCDavis Soil Models 34 | """ 35 | 36 | __author__ = 'marafi' 37 | 38 | from OpenSeesAPI.OpenSees import OpenSees 39 | 40 | class ElasticIsotropic(OpenSees): 41 | """ 42 | nDMaterial ElasticIsotropic $matTag $E $v <$rho> 43 | $matTag integer tag identifying material 44 | $E elastic Modulus 45 | $v Poisson's ratio 46 | $rho mass density, optional default = 0.0. 47 | """ 48 | def __init__(self, id, E, v, rho=None, **kwargs): 49 | self._id = id 50 | self._E = E 51 | self._v = v 52 | self._rho = rho 53 | self.__dict__.update(kwargs) 54 | 55 | if self._rho == None: 56 | self._CommandLine = 'nDMaterial ElasticIsotropic %d %f %f '%(self._id, self._E, self._v) 57 | else: 58 | self._CommandLine = 'nDMaterial ElasticIsotropic %d %f %f %f'%(self._id, self._E, self._v, self._rho) 59 | 60 | class PlaneStress(OpenSees): 61 | """ 62 | nDMaterial PlaneStress $matTag $threeDtag 63 | $matTag integer tag identifying material 64 | $otherTag tag of perviously defined 3d ndMaterial material 65 | """ 66 | def __init__(self, id, NdMat, **kwargs): 67 | self._id = id 68 | self._NdMat = NdMat 69 | self.__dict__.update(kwargs) 70 | 71 | self._CommandLine = 'nDMaterial PlaneStress %d %d'%(self._id, self._NdMat.id) 72 | 73 | class PlaneStrain(OpenSees): 74 | """ 75 | nDMaterial PlaneStrain $matTag $threeDtag 76 | $matTag integer tag identifying material 77 | $threeDTag integer tag of previously defined 3d ndMaterial material 78 | """ 79 | def __init__(self, id, NdMat, **kwargs): 80 | self._id = id 81 | self._NdMat = NdMat 82 | self.__dict__.update(kwargs) 83 | 84 | self._CommandLine = 'nDMaterial PlaneStrain %d %d'%(self._id, self._NdMat.id) 85 | 86 | class PlaneStressUserMaterial(OpenSees): 87 | """ 88 | nDmaterial PlaneStressUserMaterial $matTag 40 7 $fc $ft $fcu $epsc0 $epscu $epstu $stc 89 | $matTag integer tag identifying material 90 | $fc concrete compressive strength at 28 days (positive) 91 | $ft concrete tensile strength (positive) 92 | $fcu concrete crushing strength (negative) 93 | $epsc0 concrete strain at maximum strength (negative) 94 | $epscu concrete strain at crushing strength (negative) 95 | $epstu ultimate tensile strain (positive) 96 | $stc shear retention factor 97 | """ 98 | def __init__(self, id, fc, ft, fcu, epsc0, epscu, epstu, stc, **kwargs): 99 | self._id = id 100 | self._fc = fc 101 | self._ft = ft 102 | self._fcu = fcu 103 | self._epsc0 = epsc0 104 | self._epscu = epscu 105 | self._epstu = epstu 106 | self._stc = stc 107 | self.__dict__.update(kwargs) 108 | 109 | self._CommandLine = 'nDMaterial PlaneStressUserMaterial %d %f %f %f %f %f %f %f'%(self._id, self._fc, self._ft, self._fcu, self._epsc0, self._epscu, self._epstu, self._stc) 110 | 111 | class PlateFromPlaneStress(OpenSees): 112 | """ 113 | nDmaterial PlateFromPlaneStress $newmatTag $matTag $OutofPlaneModulus 114 | $newmatTag new integer tag identifying material deriving from pre-defined PlaneStressUserMaterial 115 | $matTag integer tag identifying PlaneStressUserMaterial 116 | $OutofPlaneModulus shear modulus of out plane 117 | """ 118 | def __init__(self, id, mat, OutofPlaneModulus, **kwargs): 119 | self._id = id 120 | self._mat = mat 121 | self._OutofPlaneModulus = OutofPlaneModulus 122 | self.__dict__.update(kwargs) 123 | 124 | self._CommandLine = 'nDMaterial PlateFromPlaneStress %d %d %f'%(self._id, self._mat.id, self._OutofPlaneModulus) 125 | 126 | class PlateRebar(OpenSees): 127 | """ 128 | nDmaterial PlateRebar $newmatTag $matTag $sita 129 | 130 | $newmatTag new integer tag identifying material deriving from pre-defined uniaxial steel material 131 | $matTag integer tag identifying uniaxial steel material 132 | $sita define the angle of steel layer, 90 (longitudinal steel), 0 (tranverse steel) 133 | """ 134 | def __init__(self, id, mat, sita, **kwargs): 135 | self._id = id 136 | self._mat = mat 137 | self._sita = sita 138 | self.__dict__.update(kwargs) 139 | 140 | self._CommandLine = 'nDMaterial PlateRebar %d %d %f'%(self._id, self._mat.id, self._sita) 141 | 142 | class PlateFiber(OpenSees): 143 | """ 144 | This command is used to construct a plate-fiber material wrapper which converts any three-dimensional material into a plate fiber material (by static condensation) appropriate for shell analysis. 145 | 146 | nDMaterial PlateFiber $matTag $threeDTag 147 | $matTag integer tag identifying material 148 | $threeDTag material tag for a previously-defined three-dimensional material 149 | """ 150 | def __init__(self, id, mat, **kwargs): 151 | self._id = id 152 | self._mat = mat 153 | self.__dict__.update(kwargs) 154 | 155 | self._CommandLine = 'nDMaterial PlateFiber %d %d'%(self._id, self._mat.id) 156 | 157 | 158 | class LayeredShell(OpenSees): 159 | """ 160 | section LayeredShell $sectionTag $nLayers $matTag1 $thickness1...$matTagn $thicknessn 161 | $sectionTag 162 | unique tag among sections 163 | $nLayers total numbers of layers 164 | $matTag1 material tag of first layer 165 | $thickness1 thickness of first layer 166 | ... 167 | $matTagn material tag of last layer 168 | $thicknessn thickness of last layer 169 | """ 170 | def __init__(self, id, materialList, thicknessList, **kwargs): 171 | self._id = id 172 | self._nLayers = len(materialList) 173 | self._materialList = materialList 174 | self._thicknessList = thicknessList 175 | self.__dict__.update(kwargs) 176 | 177 | self._layers = '' 178 | for i in range(len(materialList)): 179 | self._layers += '%d %f'%(materialList[i].id,thicknessList[i]) 180 | self._CommandLine = 'section LayeredShell %d %d %s'%(self._id, self._nLayers, self._layers) 181 | 182 | 183 | 184 | """ 185 | nDmaterial PlaneStressUserMaterial $matTag 40 7 $fc $ft $fcu $epsc0 $epscu $epstu $stc 186 | $matTag 187 | integer tag identifying material 188 | $fc 189 | concrete compressive strength at 28 days (positive) 190 | $ft 191 | concrete tensile strength (positive) 192 | $fcu 193 | concrete crushing strength (negative) 194 | $epsc0 195 | concrete strain at maximum strength (negative) 196 | $epscu 197 | concrete strain at crushing strength (negative) 198 | $epstu 199 | ultimate tensile strain (positive) 200 | $stc 201 | shear retention factor 202 | nDmaterial PlateFromPlaneStress $newmatTag $matTag $OutofPlaneModulus 203 | $newmatTag 204 | new integer tag identifying material deriving from pre-defined PlaneStressUserMaterial 205 | $matTag 206 | integer tag identifying PlaneStressUserMaterial 207 | $OutofPlaneModulus 208 | shear modulus of out plane 209 | 2. Multi-dimensional Reinforcement Material 210 | This command is used to create the multi-dimensional reinforcement material. 211 | 212 | nDmaterial PlateRebar $newmatTag $matTag $sita 213 | $newmatTag 214 | new integer tag identifying material deriving from pre-defined uniaxial steel material 215 | $matTag 216 | integer tag identifying uniaxial steel material 217 | $sita 218 | define the angle of steel layer, 90 (longitudinal steel), 0 (tranverse steel) 219 | 3. Define the Section of the Multi-layer Shell element 220 | This command will create the section of the multi-layer shell element, including the 221 | Multi-dimensional concrete, reinforcement material and the corresponding thickness. 222 | section LayeredShell $sectionTag $nLayers $matTag1 $thickness1...$matTagn $thicknessn 223 | $sectionTag 224 | unique tag among sections 225 | $nLayers 226 | total numbers of layers 227 | $matTag1 228 | material tag of first layer 229 | $thickness1 230 | thickness of first layer 231 | 232 | $matTagn 233 | material tag of last layer 234 | $thicknessn 235 | thickness of last layer 236 | """ -------------------------------------------------------------------------------- /OpenSeesAPI/Model/Element/Material/Section.py: -------------------------------------------------------------------------------- 1 | __author__ = 'marafi' 2 | 3 | """ 4 | section secType? secTag? arg1? ... 5 | 6 | The type of section created and the additional arguments required depends on the secType? provided in the command. 7 | 8 | NOTE: 9 | The valid queries to any section when creating an ElementRecorder are 'force', and 'deformation'. Some sections have additional queries to which they will respond. These are documented in the NOTES section for those sections. 10 | 11 | The following contain information about secType? and the args required for each of the available section types: 12 | Elastic Section 13 | Fiber Section 14 | NDFiber Section 15 | Wide Flange Section 16 | RC Section 17 | Parallel Section 18 | Section Aggregator 19 | Uniaxial Section 20 | Elastic Membrane Plate Section 21 | Plate Fiber Section 22 | Bidirectional Section 23 | Isolator2spring Section 24 | """ 25 | 26 | from OpenSeesAPI.OpenSees import OpenSees 27 | 28 | class Elastic(OpenSees): 29 | """ 30 | section Elastic $secTag $E $A $Iz <$G $alphaY> 31 | section Elastic $secTag $E $A $Iz $Iy $G $J <$alphaY $alphaZ> 32 | 33 | $secTag unique section tag 34 | $E Young's Modulus 35 | $A cross-sectional area of section 36 | $Iz second moment of area about the local z-axis 37 | $Iy second moment of area about the local y-axis (required for 3D analysis) 38 | $G Shear Modulus (optional for 2D analysis, required for 3D analysis) 39 | $J torsional moment of inertia of section (required for 3D analysis) 40 | $alphaY shear shape factor along the local y-axis (optional) 41 | $alphaZ shear shape factor along the local z-axis (optional) 42 | """ 43 | def __init__(self, id, E, A, Iz, G=None, Iy=None, J=None, AlphaY=None, AlphaZ=None, **kwargs): 44 | self._id = id 45 | self._E = E 46 | self._A = A 47 | self._Iz = Iz 48 | self._G = G 49 | self._Iy =Iy 50 | self._J = J 51 | self._AlphaY = AlphaY 52 | self._AlphaZ = AlphaZ 53 | self._EndCommand = '' 54 | self.__dict__.update(kwargs) 55 | 56 | if self._J==None: 57 | if self._self._G != None: 58 | self._EndCommand = '%f %f'%(self._G, self._AlphaY) 59 | self._CommandLine = 'section Elastic %d %f %f %f %s'%(self._id, self._E, self._A, self._Iz, self._EndCommand) 60 | else: 61 | if self._AlphaY != None: 62 | self._EndCommand = '%f %f'%(self._AlphaY, self._AlphaZ) 63 | self._CommandLine = 'section Elastic %d %f %f %f %f %f %f %s'%(self._id, self._E, self._A , self._Iz, self._Iy, self._G, self._J, self._EndCommand) 64 | 65 | class WFSection2d(OpenSees): 66 | """ 67 | section WFSection2d $secTag $matTag $d $tw $bf $tf $Nfw $Nff 68 | 69 | $secTag unique section tag 70 | $matTag tag of uniaxialMaterial assigned to each fiber 71 | $d section depth 72 | $tw web thickness 73 | $bf flange width 74 | $tf flange thickness 75 | $Nfw number of fibers in the web 76 | $Nff number of fibers in each flange 77 | """ 78 | def __init__(self, id, Mat, d, tw, bf, tf, Nfw, Nff, **kwargs): 79 | self._id = id 80 | self._Mat = Mat 81 | self._d = d 82 | self._tw = tw 83 | self._bf = bf 84 | self._tf = tf 85 | self._Nfw = Nfw 86 | self._Nff = Nff 87 | self.__dict__.update(kwargs) 88 | 89 | self._CommandLine = 'section WFSection2d %d %d %f %f %f %f %f %f'%(self._id, self._Mat.id, self._d, self._tw, self._bf, self._tf, self._Nfw, self._Nff) 90 | 91 | class RCSection2d(OpenSees): 92 | """ 93 | section RCSection2d $secTag $coreTag $coverTag $steelTag $d $b $cover $Atop $Abot $Aside $Nfcore $Nfcover $Nfs 94 | $secTag unique section tag 95 | $coreTag tag of uniaxialMaterial assigned to each fiber in the core region 96 | $coverTag tag of uniaxialMaterial assigned to each fiber in the cover region 97 | $steelTag tag of uniaxialMaterial assigned to each reinforcing bar 98 | $d section depth 99 | $b section width 100 | $cover cover depth (assumed uniform around perimeter) 101 | $Atop area of reinforcing bars in top layer 102 | $Abot area of reinforcing bars in bottom layer 103 | $Aside area of reinforcing bars on intermediate layers 104 | $Nfcore number of fibers through the core depth 105 | $Nfcover number of fibers through the cover depth 106 | $Nfs number of bars on the top and bottom rows of reinforcement (Nfs-2 bars will be placed on the side rows) 107 | """ 108 | def __init__(self, id, coreMat, coverMat, steelMat, d, b, cover, Atop, Abot, Aside ,Nfcore ,Nfcover, Nfs, **kwargs): 109 | self._id = id 110 | self._coverMat = coverMat 111 | self._steelMat = steelMat 112 | self._coreMat = coreMat 113 | self._d = d 114 | self._b = b 115 | self._cover = cover 116 | self._Atop = Atop 117 | self._Abot = Abot 118 | self._Aside = Aside 119 | self._Nfcore = Nfcore 120 | self._Nfcover = Nfcover 121 | self._Nfs = Nfs 122 | self.__dict__.update(kwargs) 123 | 124 | self._CommandLine = 'section RCSection2d %d %d %d %f %f %f %f %f %f %d %d %d'%(self._id, self._coreMat.id, self._coverMat.id, self._steelMat.id, self._d, self._b, self._cover, self._Atop, self._Abot, self._Aside, self._Nfcore, self._Nfcover, self._Nfs) 125 | 126 | class NDFiber(OpenSees): 127 | """ 128 | section NDFiber $secTag { 129 | fiber... 130 | patch... 131 | layer... 132 | ... 133 | } 134 | 135 | $secTag unique tag among all sections 136 | fiber... command to generate a single fiber. 137 | patch... command to generate a number of fibers over a geometric cross-section 138 | layer... command to generate a row of fibers along a geometric-arc 139 | """ 140 | def __init__(self, id, fibers, **kwargs): 141 | self._id = id 142 | self._fibers = fibers 143 | self.__dict__.update(kwargs) 144 | 145 | self._CommandLine = 'section Fiber %d { \n'%(self._id)+''.join(map(lambda x: ' %s\n'%x._CommandLine, self._fibers))+'}' 146 | 147 | class Aggregator(OpenSees): 148 | """ 149 | section Aggregator $secTag $matTag1 $dof1 $matTag2 $dof2 ....... <-section $sectionTag> 150 | 151 | $secTag unique section tag 152 | $matTag1 $matTag2 ... tag of previously-defined UniaxialMaterial objects 153 | $dof1 $dof2 ... the force-deformation quantity to be modeled by this section object. One of the following section dof may be used: 154 | P Axial force-deformation 155 | Mz Moment-curvature about section local z-axis 156 | Vy Shear force-deformation along section local y-axis 157 | My Moment-curvature about section local y-axis 158 | Vz Shear force-deformation along section local z-axis 159 | T Torsion Force-Deformation 160 | $sectionTag tag of previously-defined Section object to which the UniaxialMaterial objects are aggregated as additional force-deformation relationships 161 | """ 162 | def __init__(self, id, MatList, DOFList, Section=None, **kwargs): 163 | self._id = id 164 | self._MatList = MatList 165 | self._DOFList = DOFList 166 | self._Section = Section 167 | self.__dict__.update(kwargs) 168 | 169 | @property 170 | def CommandLine(self): 171 | if self._Section == None: 172 | self._CommandLine = 'section Aggregator %d %s'%(self._id, ''.join(map(lambda x: ' %d %d'%(x[0].id, x[1]), zip(*[self._MatList, self._DOFList])))) 173 | else: 174 | self._CommandLine = 'section Aggregator %d %s -section %d'%(self._id, ''.join(map(lambda x: ' %d %s'%(x[0].id, x[1]), zip(*[self._MatList, self._DOFList]))), self._Section.id) 175 | return self._CommandLine 176 | 177 | 178 | 179 | class Uniaxial(OpenSees): 180 | """ 181 | section Uniaxial $secTag $matTag $quantity 182 | 183 | $secTag unique section tag 184 | $matTag tag of uniaxial material 185 | $quantity the force-deformation quantity to be modeled by this section object. One of the following strings is used: 186 | P Axial force-deformation 187 | Mz Moment-curvature about section local z-axis 188 | Vy Shear force-deformation along section local y-axis 189 | My Moment-curvature about section local z-axis 190 | Vz Shear force-deformation along section local z-axis 191 | T Torsion Force-Deformation 192 | """ 193 | def __init__(self, id, Mat, quantity): 194 | self._id = id 195 | self._Mat = Mat 196 | self._quantity = quantity 197 | 198 | self._CommandLine = 'section Uniaxial %d %d %s'%(self._id, self._Mat.id, self._quantity) 199 | 200 | class ElasticMembranePlateSection(OpenSees): 201 | """ 202 | section ElasticMembranePlateSection $secTag $E $nu $h $rho 203 | 204 | $secTag unique section tag 205 | $E Young's Modulus 206 | $nu Poisson's Ratio 207 | $h depth of section 208 | $rho mass density 209 | """ 210 | def __init__(self, id, E, nu, h, rho, **kwargs): 211 | self._id = id 212 | self._E = E 213 | self._nu = nu 214 | self._h = h 215 | self._rho = rho 216 | self.__dict__.update(kwargs) 217 | 218 | self._CommandLine = 'section ElasticMembranePlateSection %d %f %f %f %f'%(self._id, self._E, self._nu, self._h, self._rho) 219 | 220 | class PlateFiber(OpenSees): 221 | """ 222 | section PlateFiber $secTag $matTag $h 223 | 224 | $secTag unique section tag 225 | $matTag nDMaterial tag to be assigned to each fiber 226 | $h plate thickness 227 | """ 228 | def __init__(self, id, Mat, h): 229 | self._id = id 230 | self._Mat = Mat 231 | self._h = h 232 | 233 | self._CommandLine = 'section PlateFiber %d %d %f'%(self._id, self._Mat.id, self._h) 234 | 235 | class FiberSection(OpenSees): 236 | """ 237 | This commnand allows the user to construct a FiberSection object. Each FiberSection object is composed of Fibers, with each fiber containing a UniaxialMaterial, an area and a location (y,z). The command to generate FiberSection object contains in { } the commands to generate all the fibers in the object. To construct a FiberSection and populate it, the following command is used: 238 | section Fiber $secTag <-GJ $GJ> { 239 | fiber... 240 | patch... 241 | layer... 242 | ... 243 | } 244 | 245 | $secTag unique tag among sections 246 | $GJ linear-elastic torsional stiffness assigned to the section (optional, default = no torsional stiffness) 247 | fiber... command to generate a single fiber 248 | patch... command to generate a number of fibers over a geometric cross-section 249 | layer... command to generate a row of fibers along a geometric-arc 250 | """ 251 | def __init__(self, id, fibers, GJ=None, **kwargs): 252 | self._id = id 253 | self._fibers = fibers 254 | self._GJ = GJ 255 | 256 | self.__dict__.update(kwargs) 257 | 258 | self._EndCommand = '' 259 | if self._GJ != None: 260 | self._EndCommand = '-GJ %f'%self._GJ 261 | self._CommandLine = 'section Fiber %d %s { \n'%(self._id, self._EndCommand)+''.join(map(lambda x: ' %s\n'%x._CommandLine, self._fibers))+'}' 262 | 263 | class Fiber: 264 | class Fiber(object): 265 | """ 266 | fiber $yLoc $zLoc $A $matTag 267 | 268 | $yLoc y coordinate of the fiber in the section (local coordinate system) 269 | $zLoc z coordinate of the fiber in the section (local coordinate system) 270 | $A area of the fiber. 271 | $matTag material tag associated with this fiber (UniaxialMaterial tag for a FiberSection and NDMaterial tag for use in an NDFiberSection). 272 | """ 273 | def __init__(self, yLoc, zLoc, A, Mat, **kwargs): 274 | self._yLoc = yLoc 275 | self._zLoc = zLoc 276 | self._A = A 277 | self._Mat = Mat 278 | self.__dict__.update(kwargs) 279 | 280 | self._CommandLine = 'fiber %f %f %f %d'%(self.yLoc, self._zLoc, self._A, self._Mat.id) 281 | 282 | class Layer: 283 | class Straight(object): 284 | """ 285 | layer straight $matTag $numFiber $areaFiber $yStart $zStart $yEnd $zEnd 286 | 287 | $matTag material tag of previously created material (UniaxialMaterial tag for a FiberSection or NDMaterial tag for use in an NDFiberSection) 288 | $numFibers number of fibers along line 289 | $areaFiber area of each fiber 290 | $yStart $zEnd y and z-coordinates of first fiber in line (local coordinate system) 291 | $$yEnd $zEnd y and z-coordinates of last fiber in line (local coordinate system) 292 | """ 293 | def __init__(self, Mat, numFiber, areaFiber ,yStart ,zStart ,yEnd ,zEnd ,**kwargs): 294 | self._Mat = Mat 295 | self._numFiber = numFiber 296 | self._areaFiber = areaFiber 297 | self._yStart = yStart 298 | self._zStart = zStart 299 | self._yEnd = yEnd 300 | self._zEnd = zEnd 301 | self.__dict__.update(kwargs) 302 | 303 | self._CommandLine = 'layer straight %d %d %f %f %f %f %f'%(self._Mat.id, self._numFiber, self._areaFiber, self._yStart, self._zStart, self._yEnd, self._zEnd) 304 | 305 | class Circ(object): 306 | """ 307 | layer circ $matTag $numFiber $areaFiber $yCenter $zCenter $radius <$startAng $endAng> 308 | 309 | $matTag material tag of previously created material (UniaxialMaterial tag for a FiberSection or NDMaterial tag for use in an NDFiberSection) 310 | $numFiber number of fibers along arc 311 | $areaFiber area of each fiber 312 | $yCenter $zCenter y and z-coordinates of center of circular arc 313 | $radius radius of circlular arc 314 | $startAng starting angle (optional, default = 0.0) 315 | $endAng ending angle (optional, default = 360.0 - 360/$numFiber) 316 | """ 317 | def __init__(self, Mat, numFiber, areaFiber, yCenter, zCenter, radius, startAng=None, endAng=None, **kwargs): 318 | self._Mat = Mat 319 | self._numFiber = numFiber 320 | self._areaFiber = areaFiber 321 | self._yCenter = yCenter 322 | self._zCenter = zCenter 323 | self._radius = radius 324 | self._startAng = startAng 325 | self._endAng = endAng 326 | self.__dict__.update(kwargs) 327 | 328 | if startAng != None: 329 | self._EndCommand = '%f %f'%(self._startAng, self._endAng) 330 | else: 331 | self._EndCommand = '' 332 | self._CommandLine = 'layer circ %d %d %f %f %f %f %s'%(self._Mat.id, self._numFiber, self._areaFiber, self._yCenter, self._zCenter, self._radius, self._EndCommand) 333 | 334 | class Patch: 335 | class Quad(object): 336 | """ 337 | patch quad $matTag $numSubdivIJ $numSubdivJK $yI $zI $yJ $zJ $yK $zK $yL $zL 338 | $matTag tag of previously defined material (UniaxialMaterial tag for a FiberSection or NDMaterial tag for use in an NDFiberSection) 339 | $numSubdivIJ number of subdivisions (fibers) in the IJ direction. 340 | $numSubdivJK number of subdivisions (fibers) in the JK direction. 341 | $yI $zI y & z-coordinates of vertex I (local coordinate system) 342 | $yJ $zJ y & z-coordinates of vertex J (local coordinate system) 343 | $yK $zK y & z-coordinates of vertex K (local coordinate system) 344 | $yL $zL y & z-coordinates of vertex L (local coordinate system) 345 | """ 346 | def __init__(self, Mat, numSubDivIJ, numSubDibJK, yI, zI, yJ, zJ, yK, zK, yL, zL, **kwargs): 347 | self._Mat = Mat 348 | self._numSubDivIJ = numSubDivIJ 349 | self._numSubDivJK = numSubDibJK 350 | self._yI = yI 351 | self._zI = zI 352 | self._yJ = yJ 353 | self._zJ = zJ 354 | self._yK = yK 355 | self._zK = zK 356 | self._yL = yL 357 | self._zL = zL 358 | self.__dict__.update(kwargs) 359 | 360 | self._CommandLine = 'patch quad %d %d %d %f %f %f %f %f %f %f %f'%(self._Mat.id, self._numSubDivIJ, self._numSubDivJK, self._yI, self._zI, self._yJ, self._zJ, self._yK, self._zK, self._yL, self._zL) 361 | 362 | class Rect(object): 363 | """ 364 | patch rect $matTag $numSubdivY $numSubdivZ $yI $zI $yJ $zJ 365 | $matTag tag of previously defined material (UniaxialMaterial tag for a FiberSection or NDMaterial tag for use in an NDFiberSection) 366 | $numSubdivY number of subdivisions (fibers) in the local y direction. 367 | $numSubdivZ number of subdivisions (fibers) in the local z direction. 368 | $yI $zI y & z-coordinates of vertex I (local coordinate system) 369 | $yJ $zJ y & z-coordinates of vertex J (local coordinate system) 370 | """ 371 | def __init__(self, Mat, numSubDivIJ, numSubDibJK, yI, zI, yJ, zJ, **kwargs): 372 | self._Mat = Mat 373 | self._numSubDivIJ = numSubDivIJ 374 | self._numSubDivJK = numSubDibJK 375 | self._yI = yI 376 | self._zI = zI 377 | self._yJ = yJ 378 | self._zJ = zJ 379 | self.__dict__.update(kwargs) 380 | 381 | self._CommandLine = 'patch rect %d %d %d %f %f %f %f'%(self._Mat.id, self._numSubDivIJ, self._numSubDivJK, self._yI, self._zI, self._yJ, self._zJ) 382 | 383 | class Circ(object): 384 | """ 385 | patch circ $matTag $numSubdivCirc $numSubdivRad $yCenter $zCenter $intRad $extRad <$startAng $endAng> 386 | 387 | $matTag tag of previously defined material (UniaxialMaterial tag for a FiberSection or NDMaterial tag for use in an NDFiberSection) 388 | $numSubdivCirc number of subdivisions (fibers) in the circumferential direction 389 | $numSubdivRad number of subdivisions (fibers) in the radial direction. 390 | $yCenter $zCenter y & z-coordinates of the center of the circle 391 | $intRad internal radius 392 | $extRad external radius 393 | $startAng starting angle (optional. default=0.0) 394 | $endAng ending angle (optional. default=360.0) 395 | """ 396 | def __init__(self, Mat, numSubDivIJ, numSubDibJK, yCenter, zCenter, intRad, extRad, startAng=None, endAng=None, **kwargs): 397 | self._Mat = Mat 398 | self._numSubDivIJ = numSubDivIJ 399 | self._numSubDivJK = numSubDibJK 400 | self._yCenter = yCenter 401 | self._zCenter = zCenter 402 | self._intRad = intRad 403 | self._extRad = extRad 404 | self._startAng = startAng 405 | self._endAng = endAng 406 | self.__dict__.update(kwargs) 407 | 408 | if startAng != None: 409 | self._EndCommand = '%f %f'%(self._startAng, self._endAng) 410 | else: 411 | self._EndCommand = '' 412 | self._CommandLine = 'patch circ %d %d %d %f %f %f %f %s'%(self._Mat.id, self._numSubDivIJ, self._numSubDivJK, self._yCenter, self._zCenter, self._intRad, self._extRad, self._EndCommand) 413 | 414 | -------------------------------------------------------------------------------- /OpenSeesAPI/Model/Element/Material/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'marafi' 2 | 3 | # Import Folder with Several Classes 4 | from OpenSeesAPI.Model.Element.Material import UniaxialMaterial 5 | from OpenSeesAPI.Model.Element.Material import NDMaterial 6 | from OpenSeesAPI.Model.Element.Material import Section 7 | 8 | # Import One Class Files 9 | -------------------------------------------------------------------------------- /OpenSeesAPI/Model/Element/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Nasser' 2 | 3 | # Import Folder with Several Classes 4 | from OpenSeesAPI.Model.Element import Element 5 | from OpenSeesAPI.Model.Element import GeomTransf 6 | from OpenSeesAPI.Model.Element import Material 7 | 8 | # Import One Class Files 9 | -------------------------------------------------------------------------------- /OpenSeesAPI/Model/Node.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class can be used to construct Nodes, Mass Nodes and Raleigh 3 | """ 4 | 5 | __author__ = 'marafi' 6 | 7 | 8 | from OpenSeesAPI.OpenSees import OpenSees 9 | 10 | class Node(OpenSees): 11 | """ 12 | This command is used to construct a Node object. It assigns coordinates and masses to the Node object. 13 | 14 | node $nodeTag (ndm $coords) <-mass (ndf $massValues)> 15 | $nodeTag integer tag identifying node 16 | $coords nodal coordinates (ndm arguments) 17 | $massValues nodal mass corresponding to each DOF (ndf arguments) (optional)) 18 | The optional -mass string allows analyst the option of associating nodal mass with the node 19 | 20 | EXAMPLE: 21 | node 1 0.0 0.0 0.0; # x,y,z coordinates (0,0,0) of node 1 22 | node 2 0.0 120. 0.0; # x,y,z coordinates (0,120,0) of node 2 23 | """ 24 | def __init__(self, id, X, Y, Z=None, MassX = None, MassY = None, MassZ = None, **kwargs): 25 | self._X = X 26 | self._Y = Y 27 | self._Z = Z 28 | self._id = id 29 | self._MassX = MassX 30 | self._MassY = MassY 31 | self._MassZ = MassZ 32 | 33 | self._Optional = None 34 | if self._MassX != None: 35 | self._Optional = '-mass' 36 | for x in [self._MassX, self._MassY, self._MassZ]: 37 | if x != None: 38 | self._Optional += ' %f'%x 39 | 40 | self.__dict__.update(kwargs) 41 | 42 | if Z == None: 43 | self._CommandLine = 'node %d %f %f'%(self._id, self._X, self._Y) 44 | else: 45 | self._CommandLine = 'node %d %f %f %f'%(self._id, self._X, self._Y, self._Z) 46 | 47 | @property 48 | def X(self): 49 | return self._X 50 | @property 51 | def Y(self): 52 | return self._Y 53 | @property 54 | def Z(self): 55 | return self._Z 56 | 57 | class Mass(OpenSees): 58 | def __init__(self, Node, MassList, **kwargs): 59 | self._Node = Node 60 | self._MassList = MassList 61 | self._CommandLine = 'mass %d %s'%(self._Node.id, ''.join([' %f'%x for x in self._MassList])) 62 | 63 | self.__dict__.update(kwargs) 64 | 65 | class Rayleigh(OpenSees): 66 | def __init__(self, AlphaM, BetaK, BetaKInitial, BetaKCommitted): 67 | self._AlphaM = AlphaM 68 | self._BetaK = BetaK 69 | self._BetaKInitial = BetaKInitial 70 | self._BetaKCommitted = BetaKCommitted 71 | self._CommandLine = 'rayleigh %f %f %f %f'%(self._AlphaM, self._BetaK, self._BetaKInitial, self._BetaKCommitted) -------------------------------------------------------------------------------- /OpenSeesAPI/Model/Pattern.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | Plain Pattern 4 | Uniform Excitation Pattern 5 | Multi-Support Excitation Pattern 6 | DRM Load Pattern 7 | """ 8 | 9 | __author__ = 'marafi' 10 | 11 | from OpenSeesAPI.OpenSees import OpenSees 12 | 13 | class UniformExcitation(OpenSees): 14 | """ 15 | pattern UniformExcitation $patternTag $dir -accel $tsTag <-vel0 $vel0> <-fact $cFactor> 16 | $patternTag unique tag among load patterns 17 | $dir direction in which ground motion acts 18 | 1 - corresponds to global X axis 19 | 2 - corresponds to global Y axis 20 | 3 - corresponds to global Z axis 21 | $tsTag tag of the TimeSeries series defining the acceleration history. 22 | $vel0 the initial velocity (optional, default=0.0) 23 | $cFactor constant factor (optional, default=1.0) 24 | """ 25 | def __init__(self, id, Dof, TimeSeries, **kwargs): 26 | self._id = id 27 | self._Dof = Dof 28 | self._TimeSeries = TimeSeries 29 | self._CommandLine = 'pattern UniformExcitation %d %d -accel %d'%(self._id, self._Dof, self._TimeSeries.id) 30 | self.__dict__.update(kwargs) 31 | 32 | class Plain(OpenSees): 33 | """ 34 | This commnand allows the user to construct a LoadPattern object. Each plain load pattern is associated with a TimeSeries object and can contain multiple NodalLoads, ElementalLoads and SP_Constraint objects. The command to generate LoadPattern object contains in { } the commands to generate all the loads and the single-point constraints in the pattern. To construct a load pattern and populate it, the following command is used: 35 | pattern Plain $patternTag $tsTag <-fact $cFactor> { 36 | load... 37 | eleLoad... 38 | sp... 39 | ... 40 | } 41 | 42 | NOTES: 43 | The command to generate a LoadPattern contains in { } the commands to generate all the loads and single-point constraints.. 44 | $patternTag unique tag among load patterns 45 | $tsTag the tag of the time series to be used in the load pattern 46 | $cFactor constant factor (optional, default=1.0) 47 | load... command to nodal load 48 | eleLoad ... command to generate elemental load 49 | sp ... command to generate single-point constraint 50 | """ 51 | def __init__(self, id, TimeSeriesTag, Objects, Optional='', **kwargs): 52 | self._id = id 53 | self._TimeSeriesTag = TimeSeriesTag 54 | self._Optional = Optional 55 | self._Objects = Objects 56 | self.__dict__.update(kwargs) 57 | 58 | @property 59 | def CommandLine(self): 60 | self._CommandLine = 'pattern Plain %d %s %s { \n%s\n }'%(self._id, self._TimeSeriesTag, self._Optional, ''.join(map(lambda x: '\n'+x.CommandLine, self._Objects))) 61 | return self._CommandLine 62 | 63 | 64 | class Load(OpenSees): 65 | """ 66 | load $nodeTag (ndf $LoadValues) 67 | $nodeTag tag of node to which load is applied. 68 | $loadvalues ndf reference load values. 69 | """ 70 | 71 | def __init__(self, Node, LoadList, **kwargs): 72 | self._Node = Node 73 | self._LoadList = LoadList 74 | self.__dict__.update(kwargs) 75 | 76 | @property 77 | def CommandLine(self): 78 | self._CommandLine = 'load %d %s'%(self._Node.id, ''.join([' %f'%x for x in self._LoadList])) 79 | return self._CommandLine 80 | 81 | class EleLoad(OpenSees): 82 | """ 83 | The eleLoad command is used to construct an ElementalLoad object and add it to the enclosing LoadPattern. 84 | load $eleLoad $arg1 $arg2 $arg3 .... 85 | 86 | The element loads are only applied to line elements. Continuum elements do not accept element loads. When NDM=2, the beam column elements all accept eleLoad commands of the following form: 87 | eleLoad -ele $eleTag1 <$eleTag2 ....> -type -beamUniform $Wy <$Wx> 88 | 89 | eleLoad -range $eleTag1 $eleTag2 -type -beamPoint $Py $xL <$Px> 90 | 91 | When NDM=3, the beam column elements all accept eleLoad commands of the following form: 92 | eleLoad -ele $eleTag1 <$eleTag2 ....> -type -beamUniform $Wy $Wz <$Wx> 93 | 94 | eleLoad -range $eleTag1 $eleTag2 -type -beamPoint $Py $Pz $xL <$Px> 95 | 96 | $eleTag1 $eleTag2 ... tag of PREVIOUSLY DEFINED element 97 | $Wx mag of uniformily distributed ref load acting in direction along member length 98 | $Wy mag of uniformily distributed ref load acting in local y direction of element 99 | $Wz mag of uniformily distributed ref load acting in local z direction of element 100 | $Py mag of ref point load acting in direction along member length 101 | $Py mag of ref point load acting in local y direction of element 102 | $Pz mag of ref point load acting in local z direction of element 103 | $xL location of point load relative to node I, prescribed as fraction of element length 104 | """ 105 | def __init__(self, EleArg, ElementList, TypeArg, LoadList, **kwargs): 106 | self._EleArg = EleArg 107 | self._ElementList = ElementList 108 | self._TypeArg = TypeArg 109 | self._LoadList = LoadList 110 | self.__dict__.update(kwargs) 111 | 112 | @property 113 | def CommandLine(self): 114 | self._CommandLine = 'eleLoad %s %s %s %s'%(self._EleArg, ''.join([' %d'%x.id for x in self._ElementList]), self._TypeArg, ''.join([' %f'%x for x in self._LoadList])) 115 | return self._CommandLine 116 | 117 | class sp(OpenSees): 118 | """ 119 | sp $nodeTag $dofTag $dofValue 120 | 121 | $nodeTag tag of node to which constraint is applied. 122 | $dofTag the degree-of-freedom at the node to which constraint is applied (1 through ndf) 123 | $dofValue reference constraint value. 124 | """ 125 | def __init__(self, Node, DOF, DOFValue, **kwargs): 126 | self._Node = Node 127 | self._DOF = DOF 128 | self._DOFValue = DOFValue 129 | self.__dict__.update(kwargs) 130 | 131 | @property 132 | def CommandLine(self): 133 | self._CommandLine = 'sp %d %d %f'%(self._Node.id, self._DOF, self._DOFValue) 134 | return self._CommandLine -------------------------------------------------------------------------------- /OpenSeesAPI/Model/TimeSeries.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | Constant TimeSeries 4 | Linear TimeSeries 5 | Trigonometric TimeSeries 6 | Triangular TimeSeries 7 | Rectangular TimeSeries 8 | Pulse TimeSeries 9 | Path TimeSeries 10 | PeerMotion 11 | PeerNGAMotion 12 | """ 13 | 14 | __author__ = 'marafi' 15 | 16 | from OpenSeesAPI.OpenSees import OpenSees 17 | 18 | class Path(OpenSees): 19 | """ 20 | This command is used to construct a Path TimeSeries object. The relationship between load factor and time is input by the user as a series of discrete points in the 2d space (load factor, time). The input points can come from a file or from a list in the script. When the time specified does not match any of the input points, linear interpolation is used between points. There are many ways to specify the load path: 21 | For a load path where the factors are specified in a tcl list with a constant time interval between points: 22 | timeSeries Path $tag -dt $dt -values {list_of_values} <-factor $cFactor> 23 | For a load path where the factors are specified in a file for a constant time interval between points: 24 | timeSeries Path $tag -dt $dt -filePath $filePath <-factor $cFactor> 25 | For a load path where the values are specified at non-constant time intervals: 26 | timeSeries Path $tag -time {list_of_times} -values {list_of_values} <-factor $cFactor> 27 | For a load path where both time and values are specified in a list included in the command 28 | timeSeries Path $tag -fileTime $fileTime -filePath $filePath <-factor $cFactor> 29 | """ 30 | def __init__(self, id, dt, ValuesList): 31 | self._id = id 32 | self._dt = dt 33 | self._ValueList = ValuesList 34 | self._CommandLine = 'timeSeries Path %d -dt %f -values {%s}'%(self._id, self._dt, ''.join([' %f'%x for x in self._ValueList])) -------------------------------------------------------------------------------- /OpenSeesAPI/Model/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'marafi' 2 | 3 | # Import Folder with Several Classes 4 | from OpenSeesAPI.Model import Element 5 | from OpenSeesAPI.Model import Node 6 | from OpenSeesAPI.Model import Constraint 7 | from OpenSeesAPI.Model import TimeSeries 8 | from OpenSeesAPI.Model import Pattern 9 | 10 | # Import One Class Files 11 | from OpenSeesAPI.Model.BasicBuilder import BasicBuilder 12 | -------------------------------------------------------------------------------- /OpenSeesAPI/OpenSees.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | 4 | """ 5 | 6 | __author__ = 'Nasser' 7 | 8 | class Executable(object): 9 | def __init__(self, OpenSeesCommand, FileLocation, TCLFileName): 10 | self._OpenSeesCommand = OpenSeesCommand 11 | self._Filelocation = FileLocation 12 | self._TCLFileName = TCLFileName 13 | self._TCLFileLocation = FileLocation+TCLFileName 14 | self._CommandLines = [] 15 | self._Console = None 16 | try: 17 | self._Log = self._TCLFileName[:-4]+'.log' 18 | except: 19 | print('TCL File Name Too Short') 20 | 21 | def AddCommand(self, Command): 22 | self._CommandLines.append(Command) 23 | 24 | def StartAnalysis(self, SuppressOutput = True): 25 | # Write Command Lines to Tcl File 26 | tcl = open(self._TCLFileLocation,'w') 27 | for line in self._CommandLines: 28 | tcl.write(line+'\n') 29 | tcl.close() 30 | 31 | # import time 32 | # time.sleep(60) # Wait for the file to write 33 | 34 | # Run OpenSees 35 | print('Running OpenSees Tcl File: %s'%(self._TCLFileName)) 36 | from subprocess import Popen, PIPE, STDOUT 37 | if SuppressOutput: 38 | import os 39 | FNULL = open(os.devnull, 'w') 40 | p = Popen([self._OpenSeesCommand, self._TCLFileLocation], cwd=self._Filelocation, stdout=FNULL, stderr=STDOUT) 41 | p.wait() 42 | else: 43 | p = Popen([self._OpenSeesCommand, self._TCLFileLocation], cwd=self._Filelocation ) 44 | p.wait() 45 | 46 | def DeleteTCLFile(self): 47 | try: 48 | import os 49 | os.remove(self._TCLFileLocation) 50 | except: 51 | print('Error Deleting TCL File') 52 | 53 | def DeleteLogFile(self): 54 | try: 55 | import os 56 | os.remove(self._Filelocation+self._Log) 57 | except: 58 | print('Error Deleting LOG File') 59 | 60 | @property 61 | def LogFileName(self): 62 | return self._Log 63 | 64 | class OpenSees(object): 65 | def __init__(self): 66 | self._CommandLine = None 67 | self._Executable = Executable(None) 68 | 69 | @property 70 | def CommandLine(self): 71 | try: 72 | return self._CommandLine + '; #' + self._Notes 73 | except: 74 | return self._CommandLine 75 | 76 | @property 77 | def id(self): 78 | return self._id 79 | 80 | def Execute(self): 81 | self._Executable.StartAnalysis() 82 | 83 | def AddObject(self, Object): 84 | self._Executable.AddCommand(Object.CommandLine()) 85 | -------------------------------------------------------------------------------- /OpenSeesAPI/Output.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | 4 | """ 5 | 6 | __author__ = 'Nasser' 7 | 8 | # List of Available Commands 9 | # These commands are used to get output from OpenSees: 10 | # recorder 11 | # record 12 | # print 13 | # printA 14 | # logFile 15 | # RealTime Output Commands 16 | 17 | from OpenSeesAPI.OpenSees import OpenSees 18 | 19 | class LogFile(OpenSees): 20 | """ 21 | logFile $fileName <-append> 22 | to save the warning and error messages that the running script generates from the interpreter to an output file given by $fileName. By default the file, if it exists prior to running, is overwritten with new data. If the -append option is provided the new data is appended to the end of the existing file. 23 | """ 24 | def __init__(self, FileName): 25 | self._FileName = FileName 26 | self._CommandLine = 'logFile %s;'%FileName 27 | 28 | class Recorder: 29 | class Node(OpenSees): 30 | """ 31 | The Node recorder type records the response of a number of nodes at every converged step. The command to create a node recorder is: 32 | 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' 33 | $fileName name of file to which output is sent. 34 | file output is either in xml format (-xml option), textual (-file option) or binary (-binary option) 35 | inetAddr ip address, "xx.xx.xx.xx", of remote machine to which data is sent 36 | $port port on remote machine awaiting tcp 37 | $nSD number of significant digits (optional, default is 6) 38 | -time optional, using this option places domain time in first entry of each data line, default is to have time ommitted 39 | -closeOnWrite optional. using this option will instruct the recorder to invoke a close on the data handler after every timestep. If this is a file it will close the file on every step and then re-open it for the next step. Note, this greatly slows the execution time, but is useful if you need to monitor the data during the analysis. 40 | $deltaT time interval for recording. will record when next step is $deltaT greater than last recorder step. (optional, default: records at every time step) 41 | $tsTag the tag of a previously constructed TimeSeries, results from node at each time step are added to load factor from series 42 | $node1 $node2 .. tags of nodes whose response is being recorded (optional, default: omitted) 43 | $startNode $endNode .. tag for start and end nodes whose response is being recorded (optional, default: omitted) 44 | $regionTag a region tag; to specify all nodes in the previously defined region. (optional) 45 | $dof1 dof2 ... the specified dof at the nodes whose response is requested. 46 | $respType a string indicating response required. Response types are given in table below. 47 | disp displacement* 48 | vel velocity* 49 | accel acceleration* 50 | incrDisp incremental displacement 51 | "eigen i" eigenvector for mode i 52 | reaction nodal reaction 53 | rayleighForces damping forces 54 | 55 | RETURNS 56 | >0 an integer tag that can be used as a handle on the recorder for the remove recorder commmand. 57 | -1 recorder command failed if integer -1 returned. 58 | """ 59 | def __init__(self, FilePath, Nodes, DOFs, Variable, Optional='', FileType='-file'): 60 | self._FilePath = FilePath 61 | self._Nodes = Nodes #Node Class in List 62 | self._DOFs = DOFs #[1,2,3] 63 | self._Variable = Variable #disp, vel, accel, reaction 64 | self._FileType = FileType 65 | self._Optional = Optional #-timeSeries id for accel 66 | OutputNodes = '' 67 | for node in self._Nodes: 68 | OutputNodes += ' %d'%node.id 69 | OutputDOF = '' 70 | for dof in self._DOFs: 71 | OutputDOF += ' %d'%dof 72 | 73 | self._CommandLine = 'recorder Node %s %s %s -time -node %s -dof %s %s'%(self._FileType,self._FilePath, 74 | self._Optional, OutputNodes, 75 | OutputDOF, self._Variable) 76 | 77 | class Element(OpenSees): 78 | """ 79 | The Element recorder type records the response of a number of elements at every converged step. The response recorded is element-dependent and also depends on the arguments which are passed to the setResponse() element method. 80 | The command to create an element recorder is: 81 | recorder Element <-file $fileName> <-xml $fileName> <-binary $fileName> <-precision $nSD> <-time> <-closeOnWrite> <-dT $deltaT> <-ele ($ele1 $ele2 ...)> <-eleRange $startEle $endEle> <-region $regTag> $arg1 $arg2 ... 82 | $fileName name of file to which output is sent. 83 | file output is either in xml format (-xml option), textual (-file option) or binary (-binary option) 84 | $nSD number of significant digits (optional, default is 6) 85 | -time (optional using this option places domain time in first entry of each data line, default is to have time ommitted) 86 | -closeOnWrite optional. using this option will instruct the recorder to invoke a close on the data handler after every timestep. If this is a file it will close the file on every step and then re-open it for the next step. Note, this greatly slows the execution time, but is useful if you need to monitor the data during the analysis. 87 | $deltaT time interval for recording. will record when next step is $deltaT greater than last recorder step. (optional, default: records at every time step) 88 | $ele1 $ele2 .. tags of elements whose response is being recorded -- selected elements in domain (optional, default: omitted) 89 | $startEle $endEle .. tag for start and end elements whose response is being recorded -- range of selected elements in domain (optional, default: omitted) 90 | $regTag previously-defined tag of region of elements whose response is being recorded -- region of elements in domain (optional) 91 | $arg1 $arg2 ... arguments which are passed to the setResponse() element method 92 | 93 | RETURNS 94 | >0 an integer tag that can be used as a handle on the recorder for the remove recorder commmand. 95 | -1 recorder command failed if integer -1 returned. 96 | """ 97 | 98 | def __init__(self, FilePath, Elements, ResponseType, FileType='-file', Optional='', **kwargs): 99 | self._FilePath = FilePath 100 | self._Elements = Elements 101 | self._ResponseType = ResponseType 102 | self._FileType = FileType 103 | self._Optional = Optional 104 | 105 | self.__dict__.update(kwargs) 106 | 107 | self._CommandLine = 'recorder Element %s %s -time %s -ele %s %s'%(self._FileType, self._FilePath, 108 | self._Optional, 109 | ''.join(map(lambda x: ' %d'%x.id, self._Elements)),self._ResponseType) 110 | 111 | class NodeDisp(OpenSees): 112 | def __init__(self, Node, DOF): 113 | self._Node = Node 114 | self._DOF = DOF 115 | 116 | @property 117 | def CommandLine(self): 118 | self._CommandLine = 'nodeDisp %d %d'%(self._Node.id, self._DOF) 119 | return self._CommandLine 120 | 121 | class NodeReac(OpenSees): 122 | def __init__(self, Node, DOF): 123 | self._Node = Node 124 | self._DOF = DOF 125 | 126 | @property 127 | def CommandLine(self): 128 | self._CommandLine = 'nodeReaction %d %d'%(self._Node.id, self._DOF) 129 | return self._CommandLine 130 | 131 | class NodeEigenVector(OpenSees): 132 | def __init__(self, Node, Mode, DOF, **kwargs): 133 | self._Node = Node 134 | self._Mode = Mode 135 | self._DOF = DOF 136 | self.__dict__.update(kwargs) 137 | 138 | self._CommandLine = 'nodeEigenvector %d %d %d'%(self._Node.id, self._Mode, self._DOF) -------------------------------------------------------------------------------- /OpenSeesAPI/TCL.py: -------------------------------------------------------------------------------- 1 | """ 2 | This class is used to create the following OpenSees TCL Commands: 3 | 4 | """ 5 | 6 | __author__ = 'Nasser' 7 | 8 | from OpenSeesAPI.OpenSees import OpenSees 9 | 10 | class Puts(OpenSees): 11 | def __init__(self, Output): 12 | self._Output = Output 13 | self._CommandLine = 'puts "%s"'%Output 14 | 15 | class CodeCommentor(OpenSees): 16 | def __init__(self, Comment): 17 | self._Comment = Comment 18 | 19 | @property 20 | def CommandLine(self): 21 | self._CommandLine = '#'+self._Comment 22 | return self._CommandLine 23 | 24 | class CodeTitle(OpenSees): 25 | def __init__(self, Comment): 26 | self._Comment = Comment 27 | 28 | @property 29 | def CommandLine(self): 30 | self._CommandLine = '\n#####################\n'+ 'puts "%s"'%self._Comment+'\n#####################\n' 31 | return self._CommandLine 32 | 33 | class TCLScript(OpenSees): 34 | def __init__(self, Script): 35 | self._CommandLine = Script 36 | 37 | class LogFile(OpenSees): 38 | def __init__(self, FileName): 39 | self._CommandLine = 'logFile %s'%FileName 40 | 41 | ## Make Directory 42 | 43 | ## For Loops 44 | 45 | ## While Loops 46 | 47 | ## Print Function 48 | 49 | ## Other Functions 50 | 51 | ## Misc Command 52 | 53 | -------------------------------------------------------------------------------- /OpenSeesAPI/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'marafi' 2 | 3 | # Import Modules with Classes 4 | from OpenSeesAPI import Analysis 5 | from OpenSeesAPI import Database 6 | from OpenSeesAPI import Model # included for backwards compatibility 7 | from OpenSeesAPI import Output 8 | from OpenSeesAPI import TCL 9 | 10 | from OpenSeesAPI.Model import BasicBuilder 11 | from OpenSeesAPI.Model import Constraint 12 | from OpenSeesAPI.Model import Node 13 | from OpenSeesAPI.Model import Pattern 14 | from OpenSeesAPI.Model import TimeSeries 15 | from OpenSeesAPI.Model.Element import Element 16 | from OpenSeesAPI.Model.Element import GeomTransf 17 | from OpenSeesAPI.Model.Element import Material 18 | from OpenSeesAPI.Model.Element.Material import Section 19 | 20 | # Importing Classes 21 | from OpenSeesAPI.OpenSees import Executable 22 | from OpenSeesAPI.OpenSees import OpenSees 23 | 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenSeesAPI 2 | ![alt text](https://travis-ci.org/nassermarafi/OpenSeesAPI.svg?branch=master) 3 | 4 | OSAPI short for OpenSeesAPI is a python package that is used to write [OpenSees](http://opensees.berkeley.edu) tcl scripts quickly. 5 | OSAPI is written using an object-oriented programing style making easy to interact with other commonly used python packages like numpy, scipy and maptlotlib. 6 | 7 | 8 | ## Installation instructions 9 | 10 | - Make sure you have OpenSees [downloaded](http://opensees.berkeley.edu/OpenSees/user/download.php) and installed (including the required tcl libraries). 11 | - Add OpenSees (or OpenSeesSP/OpenSeesMP) to your system path. This can be done easily in the command prompt or terminal. 12 | 13 | Windows Users: 14 | 15 |
set PATH=%PATH%;OpenSeesPath
16 | 
17 | 18 | Mac/Linux Users: 19 | 20 |
export PATH=$PATH:~/OpenSeesPath
21 | 
22 | 23 | - Install OpenSeesAPI using pip. This can be done using the following command. 24 | 25 |
pip install OpenSeesAPI
26 | 
27 | 28 | ## Advance Users 29 | Advanced users (who intends to add classes or change the source code) can also clone this repository and then setup it in develop mode which allows you to make changes to the original source files as you run OSAPI (this is recommended as I have not included all the OpenSees classes). 30 | 31 | Instructions: 32 | - Add OpenSees to your path 33 | - In your working directory, clone GitHub respository 34 | 35 |
git clone https://github.com/nassermarafi/OpenSeesAPI
36 | 
37 | 38 | - Install OSAPI in develop mode 39 | 40 |
python setup.py develop
41 | 
42 | 43 | - Start developing OSAPI and make some pull requests 44 | 45 | ## Example Scripts 46 | 47 | Three Example Script using OSAPI are available: 48 | - [SampleScript1.py](https://raw.githubusercontent.com/nassermarafi/OpenSeesAPI/master/test/SampleScript1.py) => SDOF System with a Deteriorating Ibarra Spring 49 | - [SampleScript2.py](https://raw.githubusercontent.com/nassermarafi/OpenSeesAPI/master/test/SampleScript2.py) => 40 Story PEER - Tall Building Initiative Building with Buckling Restrained Braced Frames 50 | - [SampleScript3.py](https://raw.githubusercontent.com/nassermarafi/OpenSeesAPI/master/test/SampleScript3.py) => Moment Curvature analysis for a concrete column 51 | - [SampleScript4.py](https://raw.githubusercontent.com/nassermarafi/OpenSeesAPI/master/test/SampleScript4.py) => Dynamic Analysis of a Steel Moment Frame Structure ([Recreation of Sample OpenSees TCL Script](http://opensees.berkeley.edu/wiki/index.php/Pushover_Analysis_of_2-Story_Moment_Frame)) 52 | 53 | I am working on more. Email me (marafi [at] uw dot edu) if you have suggestions or need something specific. 54 | 55 | ## License 56 | 57 | The MIT License (MIT) 58 | 59 | Copyright (c) 2016 Nasser Marafi 60 | 61 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 62 | 63 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 64 | 65 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 66 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | ## Things that still need to be added 2 | - Add the remaining OpenSees classes 3 | - Organize how the tcl files are written... it could go something like this: 4 | - Initiate Basic Builder 5 | - Nodes 6 | - Materials 7 | - Sections 8 | - Elements 9 | - Shells 10 | - Restraints/Constraints 11 | - Output (Recorders) 12 | - Eigen 13 | - Loading 14 | - Gravity Analysis 15 | - Pushover loading 16 | - Pushover Solution Algorithm 17 | - Number 18 | - System 19 | - Analysis 20 | - Constraint 21 | - Type 22 | - Test 23 | - Algorithm 24 | - Integrator 25 | - Analysis 26 | - Ground Motions 27 | - Dynamic Solution Algorithm 28 | - Other (Anything can be put here... I sometimes like to run a pushover after a dynamic analysis to see if my structure has collapse... others might want to run another ground-motion) 29 | - Solution Algorithms need to be inserted manually or using a helper 30 | - Shorten callout so that it goes like this: 31 | - OpenSeesAPI. 32 | - Analysis. 33 | - Algorithm 34 | - Analysis 35 | - Analyze 36 | - Constraints 37 | - Eigen 38 | - Integrator 39 | - Numberer 40 | - System 41 | - Test 42 | - Node 43 | - Element 44 | - Material. 45 | - UniaxialMaterial 46 | - ND Material 47 | - Section 48 | - BasicBuilder 49 | - Constraint 50 | - Pattern 51 | - TimeSeries 52 | - TCL 53 | - Database 54 | - Output (Recorders) 55 | - Executable 56 | - Misc -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup(name='OpenSeesAPI', 4 | version='0.15.0', 5 | # install_requires=[ 6 | # "numpy", 7 | # "matplotlib", 8 | # ], 9 | description='A OpenSees Wrapper in Python', 10 | url='http://github.com/nassermarafi/OpenSeesAPI', 11 | author='Nasser Marafi', 12 | author_email='marafi@uw.edu', 13 | license='MIT', 14 | packages=['OpenSeesAPI', 15 | 'OpenSeesAPI.Analysis', 16 | 'OpenSeesAPI.Model', 17 | 'OpenSeesAPI.Model.Element', 18 | 'OpenSeesAPI.Model.Element.Material', 19 | 'OpenSeesAPI.Helpers', 20 | 'test'], 21 | zip_safe=False) 22 | -------------------------------------------------------------------------------- /test/SampleScript1.py: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | ##### This is a sample script that runs an SDOF analysis in OpenSees 3 | ##### using an Ibarra-Krawinkler Deterioation spring 4 | ##### Coded by Nasser Marafi (marafi@uw.edu) 5 | ##### Last Updated: 8/12/2015 6 | ##### Make sure to have a subfolder called /tcl/ with the OpenSees Executable File 7 | ############################################################################ 8 | __author__ = 'marafi' 9 | 10 | import os 11 | import numpy as np 12 | 13 | ########################## Input Parameters ########################## 14 | 15 | # This is Elcentro's Ground Motion in g 16 | GMData = 386.4*np.array([0.0063,0.00364,0.00099,0.00428,0.00758,0.01087,0.00682,0.00277,-0.00128,0.00368,0.00864,0.0136,0.00727,0.00094,0.0042,0.00221,0.00021,0.00444,0.00867,0.0129,0.01713,-0.00343,-0.024,-0.00992,0.00416,0.00528,0.01653,0.02779,0.03904,0.02449,0.00995,0.00961,0.00926,0.00892,-0.00486,-0.01864,-0.03242,-0.03365,-0.05723,-0.04534,-0.03346,-0.03201,-0.03056,-0.02911,-0.02766,-0.04116,-0.05466,-0.06816,-0.08166,-0.06846,-0.05527,-0.04208,-0.04259,-0.04311,-0.02428,-0.00545,0.01338,0.03221,0.05104,0.06987,0.0887,0.04524,0.00179,-0.04167,-0.08513,-0.12858,-0.17204,-0.12908,-0.08613,-0.08902,-0.09192,-0.09482,-0.09324,-0.09166,-0.09478,-0.09789,-0.12902,-0.07652,-0.02401,0.02849,0.08099,0.1335,0.186,0.2385,0.21993,0.20135,0.18277,0.1642,0.14562,0.16143,0.17725,0.13215,0.08705,0.04196,-0.00314,-0.04824,-0.09334,-0.13843,-0.18353,-0.22863,-0.27372,-0.31882,-0.25024,-0.18166,-0.11309,-0.04451,0.02407,0.09265,0.16123,0.22981,0.29839,0.23197,0.16554,0.09912,0.0327,-0.03372,-0.10014,-0.16656,-0.23299,-0.29941,-0.00421,0.29099,0.2238,0.15662,0.08943,0.02224,-0.04495,0.01834,0.08163,0.14491,0.2082,0.18973,0.17125,0.13759,0.10393,0.07027,0.03661,0.00295,-0.03071,-0.00561,0.01948,0.04458,0.06468,0.08478,0.10487,0.05895,0.01303,-0.03289,-0.07882,-0.03556,0.00771,0.05097,0.01013,-0.03071,-0.07156,-0.1124,-0.15324,-0.11314,-0.07304,-0.03294,0.00715,-0.0635,-0.13415,-0.2048,-0.12482,-0.04485,0.03513,0.1151,0.19508,0.12301,0.05094,-0.02113,-0.0932,-0.02663,0.03995,0.10653,0.17311,0.11283,0.05255,-0.00772,0.01064,0.029,0.04737,0.06573,0.02021,-0.0253,-0.07081,-0.04107,-0.01133,0.00288,0.01709,0.03131,-0.02278,-0.07686,-0.13095,-0.18504,-0.14347,-0.1019,-0.06034,-0.01877,0.0228,-0.00996,-0.04272,-0.02147,-0.00021,0.02104,-0.01459,-0.05022,-0.08585,-0.12148,-0.15711,-0.19274,-0.22837,-0.18145,-0.13453,-0.08761,-0.04069,0.00623,0.05316,0.10008,0.147,0.09754,0.04808,-0.00138,0.05141,0.1042,0.15699,0.20979,0.26258,0.16996,0.07734,-0.01527,-0.10789,-0.20051,-0.06786,0.06479,0.01671,-0.03137,-0.07945,-0.12753,-0.17561,-0.22369,-0.27177,-0.15851,-0.04525,0.06802,0.18128,0.14464,0.108,0.07137,0.03473,0.09666,0.1586,0.22053,0.18296,0.14538,0.1078,0.07023,0.03265,0.06649,0.10033,0.13417,0.10337,0.07257,0.04177,0.01097,-0.01983,0.04438,0.1086,0.17281,0.10416,0.03551,-0.03315,-0.1018,-0.07262,-0.04344,-0.01426,0.01492,-0.02025,-0.05543,-0.0906,-0.12578,-0.16095,-0.19613,-0.14784,-0.09955,-0.05127,-0.00298,-0.01952,-0.03605,-0.05259,-0.04182,-0.03106,-0.02903,-0.02699,0.02515,0.0177,0.02213,0.02656,0.00419,-0.01819,-0.04057,-0.06294,-0.02417,0.0146,0.05337,0.02428,-0.0048,-0.03389,-0.00557,0.02274,0.00679,-0.00915,-0.02509,-0.04103,-0.05698,-0.01826,0.02046,0.00454,-0.01138,-0.00215,0.00708,0.00496,0.00285,0.00074,-0.00534,-0.01141,0.00361,0.01863,0.03365,0.04867,0.0304,0.01213,-0.00614,-0.02441,0.01375,0.01099,0.00823,0.00547,0.00812,0.01077,-0.00692,-0.02461,-0.0423,-0.05999,-0.07768,-0.09538,-0.06209,-0.0288,0.00448,0.03777,0.01773,-0.00231,-0.02235,0.01791,0.05816,0.03738,0.0166,-0.00418,-0.02496,-0.04574,-0.02071,0.00432,0.02935,0.01526,0.01806,0.02086,0.00793,-0.00501,-0.01795,-0.03089,-0.01841,-0.00593,0.00655,-0.02519,-0.05693,-0.04045,-0.02398,-0.0075,0.00897,0.00384,-0.00129,-0.00642,-0.01156,-0.02619,-0.04082,-0.05545,-0.04366,-0.03188,-0.06964,-0.05634,-0.04303,-0.02972,-0.01642,-0.00311,0.0102,0.0235,0.03681,0.05011,0.02436,-0.00139,-0.02714,-0.00309,0.02096,0.04501,0.06906,0.05773,0.0464,0.03507,0.03357,0.03207,0.03057,0.0325,0.03444,0.03637,0.01348,-0.00942,-0.03231,-0.02997,-0.03095,-0.03192,-0.02588,-0.01984,-0.01379,-0.00775,-0.01449,-0.02123,0.01523,0.0517,0.08816,0.12463,0.16109,0.12987,0.09864,0.06741,0.03618,0.00495,0.0042,0.00345,0.00269,-0.05922,-0.12112,-0.18303,-0.12043,-0.05782,0.00479,0.0674,0.13001,0.08373,0.03745,0.06979,0.10213,-0.03517,-0.17247,-0.13763,-0.10278,-0.06794,-0.0331,-0.03647,-0.03984,-0.00517,0.0295,0.06417,0.09883,0.1335,0.05924,-0.01503,-0.08929,-0.16355,-0.06096,0.04164,0.01551,-0.01061,-0.03674,-0.06287,-0.08899,-0.0543,-0.01961,0.01508,0.04977,0.08446,0.05023,0.016,-0.01823,-0.05246,-0.08669,-0.06769,-0.0487,-0.0297,-0.01071,0.00829,-0.00314,0.02966,0.06246,-0.00234,-0.06714,-0.04051,-0.01388,0.01274,0.00805,0.03024,0.05243,0.02351,-0.00541,-0.03432,-0.06324,-0.09215,-0.12107,-0.0845,-0.04794,-0.01137,0.0252,0.06177,0.04028,0.0188,0.04456,0.07032,0.09608,0.12184,0.0635,0.00517,-0.05317,-0.03124,-0.0093,0.01263,0.03457,0.03283,0.03109,0.02935,0.04511,0.06087,0.07663,0.09239,0.05742,0.02245,-0.01252,0.0068,0.02611,0.04543,0.01571,-0.01402,-0.04374,-0.07347,-0.0399,-0.00633,0.02724,0.0608,0.03669,0.01258,-0.01153,-0.03564,-0.00677,0.0221,0.05098,0.07985,0.06915,0.05845,0.04775,0.03706,0.02636,0.05822,0.09009,0.12196,0.10069,0.07943,0.05816,0.03689,0.01563,-0.00564,-0.0269,-0.04817,-0.06944,-0.0907,-0.11197,-0.11521,-0.11846,-0.1217,-0.12494,-0.165,-0.20505,-0.15713,-0.10921,-0.06129,-0.01337,0.03455,0.08247,0.07576,0.06906,0.06236,0.08735,0.11235,0.13734,0.12175,0.10616,0.09057,0.07498,0.08011,0.08524,0.09037,0.06208,0.03378,0.00549,-0.02281,-0.05444,-0.0403,-0.02615,-0.01201,-0.02028,-0.02855,-0.06243,-0.03524,-0.00805,-0.04948,-0.03643,-0.02337,-0.03368,-0.01879,-0.00389,0.011,0.02589,0.01446,0.00303,-0.0084,0.00463,0.01766,0.03069,0.04372,0.02165,-0.00042,-0.02249,-0.04456,-0.03638,-0.02819,-0.02001,-0.01182,-0.02445,-0.03707,-0.04969,-0.05882,-0.06795,-0.07707,-0.0862,-0.09533,-0.06276,-0.03018,0.00239,0.03496,0.04399,0.05301,0.03176,0.01051,-0.01073,-0.03198,-0.05323,0.00186,0.05696,0.01985,-0.01726,-0.05438,-0.01204,0.03031,0.07265,0.11499,0.07237,0.02975,-0.01288,0.01212,0.03711,0.03517,0.03323,0.01853,0.00383,0.00342,-0.02181,-0.04704,-0.07227,-0.0975,-0.12273,-0.08317,-0.04362,-0.00407,0.03549,0.07504,0.1146,0.07769,0.04078,0.00387,0.00284,0.00182,-0.05513,0.04732,0.05223,0.05715,0.06206,0.06698,0.07189,0.02705,-0.01779,-0.06263,-0.10747,-0.15232,-0.12591,-0.0995,-0.07309,-0.04668,-0.02027,0.00614,0.03255,0.00859,-0.01537,-0.03932,-0.06328,-0.03322,-0.00315,0.02691,0.01196,-0.003,0.00335,0.0097,0.01605,0.02239,0.04215,0.06191,0.08167,0.03477,-0.01212,-0.01309,-0.01407,-0.05274,-0.02544,0.00186,0.02916,0.05646,0.08376,0.01754,-0.04869,-0.02074,0.00722,0.03517,-0.00528,-0.04572,-0.08617,-0.0696,-0.05303,-0.03646,-0.01989,-0.00332,0.01325,0.02982,0.01101,-0.00781,-0.02662,-0.00563,0.01536,0.03635,0.05734,0.03159,0.00584,-0.01992,-0.00201,0.01589,-0.01024,-0.03636,-0.06249,-0.0478,-0.03311,-0.04941,-0.0657,-0.082,-0.0498,-0.0176,0.0146,0.0468,0.079,0.0475,0.016,-0.0155,-0.00102,0.01347,0.02795,0.04244,0.05692,0.03781,0.0187,-0.00041,-0.01952,-0.00427,0.01098,0.02623,0.04148,0.01821,-0.00506,-0.00874,-0.03726,-0.06579,-0.026,0.0138,0.05359,0.09338,0.05883,0.02429,-0.01026,-0.0448,-0.01083,-0.01869,-0.02655,-0.03441,-0.02503,-0.01564,-0.00626,-0.01009,-0.01392,0.0149,0.04372,0.03463,0.02098,0.00733,-0.00632,-0.01997,0.00767,0.03532,0.03409,0.03287,0.03164,0.02403,0.01642,0.00982,0.00322,-0.00339,0.02202,-0.01941,-0.06085,-0.10228,-0.07847,-0.05466,-0.03084,-0.00703,0.01678,0.01946,0.02214,0.02483,0.01809,-0.00202,-0.02213,-0.00278,0.01656,0.0359,0.05525,0.07459,0.06203,0.04948,0.03692,-0.00145,0.04599,0.04079,0.03558,0.03037,0.03626,0.04215,0.04803,0.05392,0.04947,0.04502,0.04056,0.03611,0.03166,0.00614,-0.01937,-0.04489,-0.0704,-0.09592,-0.07745,-0.05899,-0.04052,-0.02206,-0.00359,0.01487,0.01005,0.00523,0.00041,-0.00441,-0.00923,-0.01189,-0.01523,-0.01856,-0.0219,-0.00983,0.00224,0.01431,0.00335,-0.0076,-0.01856,-0.00737,0.00383,0.01502,0.02622,0.01016,-0.0059,-0.02196,-0.00121,0.01953,0.04027,0.02826,0.01625,0.00424,0.00196,-0.00031,-0.00258,-0.00486,-0.00713,-0.00941,-0.01168,-0.01396,-0.0175,-0.02104,-0.02458,-0.02813,-0.03167,-0.03521,-0.04205,-0.04889,-0.03559,-0.02229,-0.00899,0.00431,0.01762,0.00714,-0.00334,-0.01383,0.01314,0.04011,0.06708,0.0482,0.02932,0.01043,-0.00845,-0.02733,-0.04621,-0.03155,-0.01688,-0.00222,0.01244,0.02683,0.04121,0.05559,0.03253,0.00946,-0.0136,-0.01432,-0.01504,-0.01576,-0.04209,-0.02685,-0.01161,0.00363,0.01887,0.03411,0.03115,0.02819,0.02917,0.03015,0.03113,0.00388,-0.02337,-0.05062,-0.0382,-0.02579,-0.01337,-0.00095,0.01146,0.02388,0.03629,0.01047,-0.01535,-0.04117,-0.06699,-0.05207,-0.03715,-0.02222,-0.0073,0.00762,0.02254,0.03747,0.04001,0.04256,0.04507,0.04759,0.0501,0.04545,0.0408,0.02876,0.01671,0.00467,-0.00738,-0.00116,0.00506,0.01128,0.0175,-0.00211,-0.02173,-0.04135,-0.06096,-0.08058,-0.06995,-0.05931,-0.04868,-0.03805,-0.02557,-0.0131,-0.00063,0.01185,0.02432,0.0368,0.04927,0.02974,0.01021,-0.00932,-0.02884,-0.04837,-0.0679,-0.04862,-0.02934,-0.01006,0.00922,0.02851,0.04779,0.02456,0.00133,-0.0219,-0.04513,-0.06836,-0.04978,-0.0312,-0.01262,0.00596,0.02453,0.04311,0.06169,0.08027,0.09885,0.06452,0.03019,-0.00414,-0.03848,-0.07281,-0.05999,-0.04717,-0.03435,-0.03231,-0.03028,-0.02824,-0.00396,0.02032,0.00313,-0.01406,-0.03124,-0.04843,-0.06562,-0.05132,-0.03702,-0.02272,-0.00843,0.00587,0.02017,0.02698,0.03379,0.04061,0.04742,0.05423,0.03535,0.01647,0.01622,0.01598,0.01574,0.00747,-0.0008,-0.00907,0.00072,0.01051,0.0203,0.03009,0.03989,0.03478,0.02967,0.02457,0.03075,0.03694,0.04313,0.04931,0.0555,0.06168,-0.00526,-0.0722,-0.06336,-0.05451,-0.04566,-0.03681,-0.03678,-0.03675,-0.03672,-0.01765,0.00143,0.02051,0.03958,0.05866,0.03556,0.01245,-0.01066,-0.03376,-0.05687,-0.04502,-0.03317,-0.02131,-0.00946,0.00239,-0.00208,-0.00654,-0.01101,-0.01548,-0.012,-0.00851,-0.00503,-0.00154,0.00195,0.00051,-0.00092,0.01135,0.02363,0.0359,0.04818,0.06045,0.07273,0.02847,-0.01579,-0.06004,-0.05069,-0.04134,-0.03199,-0.03135,-0.03071,-0.03007,-0.01863,-0.00719,0.00425,0.0157,0.02714,0.03858,0.02975,0.02092,0.02334,0.02576,0.02819,0.03061,0.03304,0.01371,-0.00561,-0.02494,-0.02208,-0.01923,-0.01638,-0.01353,-0.01261,-0.0117,-0.00169,0.00833,0.01834,0.02835,0.03836,0.04838,0.03749,0.0266,0.01571,0.00482,-0.00607,-0.01696,-0.0078,0.00136,0.01052,0.01968,0.02884,-0.00504,-0.03893,-0.02342,-0.00791,0.00759,0.0231,0.00707,-0.00895,-0.02498,-0.041,-0.05703,-0.0292,-0.00137,0.02645,0.05428,0.03587,0.01746,-0.00096,-0.01937,-0.03778,-0.02281,-0.00784,0.00713,0.0221,0.03707,0.05204,0.06701,0.08198,0.03085,-0.02027,-0.0714,-0.12253,-0.08644,-0.05035,-0.01426,0.02183,0.05792,0.094,0.13009,0.03611,-0.05787,-0.04802,-0.03817,-0.02832,-0.01846,-0.00861,-0.03652,-0.06444,-0.06169,-0.05894,-0.05618,-0.06073,-0.06528,-0.04628,-0.02728,-0.00829,0.01071,0.0297,0.03138,0.03306,0.03474,0.03642,0.04574,0.05506,0.06439,0.07371,0.08303,0.03605,-0.01092,-0.0579,-0.04696,-0.03602,-0.02508,-0.01414,-0.03561,-0.05708,-0.07855,-0.06304,-0.04753,-0.03203,-0.01652,-0.00102,0.00922,0.01946,0.0297,0.03993,0.05017,0.06041,0.07065,0.08089,-0.00192,-0.08473,-0.07032,-0.0559,-0.04148,-0.05296,-0.06443,-0.0759,-0.08738,-0.09885,-0.06798,-0.0371,-0.00623,0.02465,0.05553,0.0864,0.11728,0.14815,0.08715,0.02615,-0.03485,-0.09584,-0.071,-0.04616,-0.02132,0.00353,0.02837,0.05321,-0.00469,-0.06258,-0.12048,-0.0996,-0.07872,-0.05784,-0.03696,-0.01608,0.0048,0.02568,0.04656,0.06744,0.08832,0.1092,0.13008,0.10995,0.08982,0.06969,0.04955,0.04006,0.03056,0.02107,0.01158,0.0078,0.00402,0.00024,-0.00354,-0.00732,-0.0111,-0.0078,-0.0045,-0.0012,0.0021,0.0054,-0.00831,-0.02203,-0.03575,-0.04947,-0.06319,-0.05046,-0.03773,-0.025,-0.01227,0.00046,0.00482,0.00919,0.01355,0.01791,0.02228,0.00883,-0.00462,-0.01807,-0.03152,-0.02276,-0.01401,-0.00526,0.0035,0.01225,0.02101,0.01437,0.00773,0.0011,0.00823,0.01537,0.02251,0.01713,0.01175,0.00637,0.01376,0.02114,0.02852,0.03591,0.04329,0.03458,0.02587,0.01715,0.00844,-0.00027,-0.00898,-0.00126,0.00645,0.01417,0.02039,0.02661,0.03283,0.03905,0.04527,0.03639,0.0275,0.01862,0.00974,0.00086,-0.01333,-0.02752,-0.04171,-0.02812,-0.01453,-0.00094,0.01264,0.02623,0.0169,0.00756,-0.00177,-0.01111,-0.02044,-0.02977,-0.03911,-0.02442,-0.00973,0.00496,0.01965,0.03434,0.02054,0.00674,-0.00706,-0.02086,-0.03466,-0.02663,-0.0186,-0.01057,-0.00254,-0.00063,0.00128,0.00319,0.0051,0.00999,0.01488,0.00791,0.00093,-0.00605,0.00342,0.01288,0.02235,0.03181,0.04128,0.02707,0.01287,-0.00134,-0.01554,-0.02975,-0.04395,-0.03612,-0.02828,-0.02044,-0.0126,-0.00476,0.00307,0.01091,0.00984,0.00876,0.00768,0.00661,0.01234,0.01807,0.0238,0.02953,0.03526,0.02784,0.02042,0.013,-0.03415,-0.00628,-0.00621,-0.00615,-0.00609,-0.00602,-0.00596,-0.0059,-0.00583,-0.00577,-0.00571,-0.00564,-0.00558,-0.00552,-0.00545,-0.00539,-0.00532,-0.00526,-0.0052,-0.00513,-0.00507,-0.00501,-0.00494,-0.00488,-0.00482,-0.00475,-0.00469,-0.00463,-0.00456,-0.0045,-0.00444,-0.00437,-0.00431,-0.00425,-0.00418,-0.00412,-0.00406,-0.00399,-0.00393,-0.00387,-0.0038,-0.00374,-0.00368,-0.00361,-0.00355,-0.00349,-0.00342,-0.00336,-0.0033,-0.00323,-0.00317,-0.00311,-0.00304,-0.00298,-0.00292,-0.00285,-0.00279,-0.00273,-0.00266,-0.0026,-0.00254,-0.00247,-0.00241,-0.00235,-0.00228,-0.00222,-0.00216,-0.00209,-0.00203,-0.00197,-0.0019,-0.00184,-0.00178,-0.00171,-0.00165,-0.00158,-0.00152,-0.00146,-0.00139,-0.00133,-0.00127,-0.0012,-0.00114,-0.00108,-0.00101,-0.00095,-0.00089,-0.00082,-0.00076,-0.0007,-0.00063,-0.00057,-0.00051,-0.00044,-0.00038,-0.00032,-0.00025,-0.00019,-0.00013,-0.00006,0]+list(np.zeros(1000))) 17 | Dt = 0.02 18 | T = 1.0 19 | Dy = 2 20 | Zeta = 0.05 21 | PY = 0.05 22 | PC = 0.1 23 | LamdaSCA = 100 24 | LamdaK = 50 25 | cRate = 1 26 | Mu = 8 27 | Kappa = 0.01 28 | 29 | # OpenSeesCommand = os.getcwd()+'//tcl//OpenSees' # Path to the OpenSees Executable File 30 | OpenSeesCommand = 'OpenSees' 31 | 32 | ########################## Pre-Initialization ########################## 33 | import OpenSeesAPI 34 | import os 35 | import numpy as np 36 | 37 | g=386.1 38 | #Mass 39 | m = 1 40 | wn = 2*np.pi/T 41 | 42 | #Stiffness 43 | k = wn**2.0*m 44 | 45 | #Damping 2% 46 | c=Zeta*2*m*wn 47 | 48 | ########################## Initializing ########################## 49 | 50 | ### Create OpenSees Database 51 | 52 | import time 53 | import uuid 54 | randomnumber = str(uuid.uuid4()).replace('-','').upper() 55 | timestamp = time.strftime("%y%m%d-%H%M%S")+randomnumber 56 | ModelName = 'ExampleScript' 57 | FileName = '%s-%s.tcl'%(ModelName,timestamp) 58 | TCLFileDirectory = os.getcwd()+'/tcl/' 59 | ResultDirectory = os.getcwd()+'/tcl/Results/' 60 | 61 | if not os.path.exists(TCLFileDirectory): #Make Directory is unavailable 62 | os.makedirs(TCLFileDirectory) 63 | if not os.path.exists(ResultDirectory): #Make Directory is unavailable 64 | os.makedirs(ResultDirectory) 65 | 66 | OData = OpenSeesAPI.Database.Collector(OpenSeesCommand, TCLFileDirectory, FileName) 67 | 68 | ########################## Setup and Source Definition ########################## 69 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Initialization')) 70 | OData.AddObject(OpenSeesAPI.Model.BasicBuilder(2,3)) 71 | 72 | ########################## Define Building Geometry, Nodes and Constraints ########################## 73 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Geometry Setup')) 74 | 75 | SupportNode = OData.CreateNode(0,0) 76 | MassNode = OData.CreateNode(0,0) 77 | OData.AddConstraint(OpenSeesAPI.Model.Node.Mass(MassNode,[m,1e-6,1e-6])) 78 | 79 | ########################## Define Geometric Transformations ########################## 80 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Geometric Transformations')) 81 | 82 | #Define Geometry Transformations for Beams and Column 83 | GeoTransfLinear = OpenSeesAPI.Model.Element.GeomTransf.Linear(1) 84 | OData.AddObject(GeoTransfLinear) 85 | 86 | ############################################################################## 87 | ### All OpenSEES Objects are adding directly to the Database Beyond This Point 88 | ############################################################################## 89 | 90 | ########################## Define Materials and Sections ########################## 91 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Materials and Sections')) 92 | 93 | ########################## Define Rotational Springs for Plastic Hinge ########################## 94 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Rotational Springs for Plastic Hinge')) 95 | 96 | #Define Rotational Spring 97 | #### Collector Should Give ID 98 | 99 | ThetaP = Dy*Mu - Dy 100 | Ult = k*Dy + k*PY*ThetaP 101 | ThetaPC = Ult/(k*PC) 102 | Spring = OpenSeesAPI.Model.Element.Material.UniaxialMaterial.ModIMKPinched(1,k,PY,PY,k*Dy,-1*k*Dy, 0.1, 0.1, 0.5, LamdaSCA,LamdaSCA,LamdaSCA,LamdaK,cRate,cRate,cRate,cRate,ThetaP, ThetaP, ThetaPC, ThetaPC, Kappa, Kappa, (ThetaPC+ThetaP+Dy)*2, (ThetaPC+ThetaP+Dy)*2, 1.0, 1.0) 103 | OData.AddMaterial(Spring) 104 | 105 | ########################## Define Elements ########################## 106 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Elements')) 107 | OData.AddElement(OpenSeesAPI.Model.Element.Element.ZeroLength(OData.GetFreeElementId(9,1),SupportNode, MassNode, [Spring],[1])) 108 | 109 | 110 | ########################## Define Restraints/Constraints ########################## 111 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.Fix(SupportNode,[1,1,1])) 112 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.Fix(MassNode,[0,1,1])) 113 | 114 | ############################################################################## 115 | ### Start Writing Elements to the Executible File 116 | ############################################################################## 117 | 118 | ########################## Write Model to TCL File ########################## 119 | OData.WriteModel() 120 | 121 | ########################## Eigenvalue Analysis ########################## 122 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Eigenvalue Analysis')) 123 | OData.AddObject(OpenSeesAPI.Analysis.Eigen(1, fullGenLapack=True)) 124 | 125 | ########################## Rayleigh Damping ########################## 126 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Rayleigh Damping')) 127 | # Adding Rayleigh Damping to the Mass Matrix Only 128 | OData.AddObject(OpenSeesAPI.Model.Node.Rayleigh(2 * Zeta * 2 * np.pi / T, 0, 0, 0)) 129 | 130 | ########################## Loads ########################## 131 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Loads')) 132 | 133 | ########################## Time Series ########################## 134 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Time Series')) 135 | 136 | TimeSeries = OpenSeesAPI.Model.TimeSeries.Path(1,Dt, GMData) 137 | OData.AddObject(TimeSeries) 138 | 139 | ########################## Recorders ########################## 140 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Recorder Setup')) 141 | 142 | OutputFolder = 'Results' 143 | 144 | Displacement_File_Name = '%s-NodeD-%s.dat'%(ModelName,timestamp) 145 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Displacement_File_Name, [MassNode], [1], 'disp')) 146 | 147 | Velocity_File_Name = '%s-NodeV-%s.dat'%(ModelName,timestamp) 148 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Velocity_File_Name, [MassNode], [1], 'vel')) 149 | 150 | Acceleration_File_Name = '%s-NodeA-%s.dat'%(ModelName,timestamp) 151 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Acceleration_File_Name, [MassNode], [1], 'accel','-timeSeries %d'%TimeSeries.id)) 152 | 153 | Reaction_File_Name = '%s-NodeReact-%s.dat'%(ModelName,timestamp) 154 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Reaction_File_Name, [SupportNode], [1], 'reaction')) 155 | 156 | ########################## Display Results ########################## 157 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Display Results')) 158 | 159 | ########################## Gravity Analysis ########################## 160 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Gravity Analysis')) 161 | 162 | ########################## Pushover Analysis ########################## 163 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Pushover Analysis')) 164 | 165 | ########################## Time History Analysis ########################## 166 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Time History Analysis')) 167 | 168 | #Analysis Options 169 | OData.AddObject(OpenSeesAPI.Analysis.Constraints.Transformation()) 170 | OData.AddObject(OpenSeesAPI.Analysis.Numberer.RCM()) 171 | OData.AddObject(OpenSeesAPI.Analysis.System.BandGeneral()) 172 | OData.AddObject(OpenSeesAPI.Analysis.Test.EnergyIncr(1e-6, 10)) 173 | OData.AddObject(OpenSeesAPI.Analysis.Algorithm.KrylovNewton()) 174 | OData.AddObject(OpenSeesAPI.Analysis.Integrator.Transient.Newmark(0.5,0.25)) 175 | OData.AddObject(OpenSeesAPI.Analysis.Analysis.Transient()) 176 | 177 | #Load Pattern 178 | OData.AddObject(OpenSeesAPI.Model.Pattern.UniformExcitation(400,1,TimeSeries)) 179 | 180 | #Run Analysis 181 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok 0;')) 182 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set Nsteps %d;'%len(GMData))) 183 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set step 0;')) 184 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('while {$ok == 0 & $step < [expr $Nsteps +1]} {')) 185 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok [analyze 1 %f]'%Dt)) 186 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('puts "Running Time History Step: $step out of %d"'%len(GMData))) 187 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set step [expr $step+1]')) 188 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('}')) 189 | 190 | ########################## Close File ########################## 191 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Close File')) 192 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('wipe;')) 193 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('puts "Models Run Complete";')) 194 | 195 | ############################################################################## 196 | ### Start Running OpenSees File 197 | ############################################################################## 198 | 199 | ########################## Plot Geometry ########################## 200 | 201 | 202 | ########################## Run OpenSees Script ########################## 203 | OData.Executable.StartAnalysis(SuppressOutput=False) 204 | 205 | ########################## Plot Results ########################## 206 | Displ = np.loadtxt(ResultDirectory+'/'+Displacement_File_Name) 207 | Vel = np.loadtxt(ResultDirectory+'/'+Velocity_File_Name) 208 | Acc = np.loadtxt(ResultDirectory+'/'+Acceleration_File_Name) 209 | Reac = np.loadtxt(ResultDirectory+'/'+Reaction_File_Name) 210 | 211 | MaxD = max(abs(Displ[:,1])) 212 | MaxV = max(abs(Vel[:,1])) 213 | MaxA = max(abs(Acc[:,1])) 214 | 215 | try: 216 | os.remove(TCLFileDirectory+'/%s-%s.out'%(ModelName,timestamp)) 217 | except: 218 | pass 219 | 220 | os.remove(TCLFileDirectory+'/%s-%s.tcl'%(ModelName,timestamp)) 221 | os.remove(ResultDirectory+'/'+Displacement_File_Name) 222 | os.remove(ResultDirectory+'/'+Velocity_File_Name) 223 | os.remove(ResultDirectory+'/'+Acceleration_File_Name) 224 | os.remove(ResultDirectory+'/'+Reaction_File_Name) 225 | 226 | DataPoints = len(GMData) 227 | 228 | t = Acc[0:DataPoints,0] 229 | ag = GMData[:]/g 230 | a = Acc[0:DataPoints,1] 231 | fs = -1*Reac[0:DataPoints,1]/(k*Dy) 232 | u = Displ[0:DataPoints,1]/Dy 233 | 234 | MaxU = max(abs(Displ[0:DataPoints,1])) 235 | MaxV = max(abs(Vel[0:DataPoints,1])) 236 | MaxA = max(abs(Acc[0:DataPoints,1])) 237 | MaxF = max(abs(Reac[0:DataPoints,1])) 238 | 239 | DArray = Displ[:,1] 240 | for i in range(0,len(DArray)): 241 | if abs(DArray[i]) == max(abs(DArray)): 242 | TimeAtMax = float(i)/float(len(DArray)) 243 | break 244 | 245 | Stiffness = [] 246 | Collapse = 0 247 | 248 | for i in range(1,len(Displ[0:DataPoints,1])): 249 | if (Displ[i,1]-Displ[i-1,1]) != 0.0: 250 | Stiffness.append(abs(Reac[i,1]-Reac[i-1,1])/abs(Displ[i,1]-Displ[i-1,1])) 251 | else: 252 | Stiffness.append(k) 253 | 254 | import matplotlib.pylab as plt 255 | plt.figure(figsize=(12,12)) 256 | plt.subplot(2,2,1) 257 | plt.plot(t,ag,color='#000000') 258 | plt.xlabel('Time, s') 259 | plt.ylabel('$a_g$, g') 260 | 261 | plt.subplot(2,2,2) 262 | plt.plot(u,fs,color='#000000') 263 | plt.xlabel('$u/\delta_y$') 264 | plt.ylabel('$f_s/f_y$') 265 | 266 | plt.subplot(2,2,3) 267 | plt.plot(t,a,color='#000000') 268 | plt.xlabel('Time, t') 269 | plt.ylabel('$a$, g') 270 | 271 | plt.subplot(2,2,4) 272 | plt.plot(u,t,color='#000000') 273 | plt.xlabel('$u/\delta_y$') 274 | plt.ylabel('Time, t') 275 | 276 | plt.show() 277 | -------------------------------------------------------------------------------- /test/SampleScript3.py: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | ##### This is a sample script that runs moment curvature analysis for a concrete columns 3 | ##### Coded by Nasser Marafi (marafi@uw.edu) 4 | ##### Last Updated: 12/15/2015 5 | ##### Make sure to have a subfolder called /tcl/ with the OpenSees Executable File 6 | ############################################################################ 7 | __author__ = 'marafi' 8 | 9 | import os 10 | import numpy as np 11 | 12 | ########################## Input Parameters ########################## 13 | 14 | # OpenSeesCommand = os.getcwd()+'/tcl/OpenSees' # Path to the OpenSees Executable File 15 | OpenSeesCommand = 'OpenSees' # Make sure Opensees is in your path if you use this 16 | 17 | ########################## Pre-Initialization ########################## 18 | import OpenSeesAPI 19 | import os 20 | import numpy as np 21 | 22 | ########################## Initializing ########################## 23 | 24 | ### Create OpenSees Database 25 | 26 | import time 27 | import uuid 28 | randomnumber = str(uuid.uuid4()).replace('-','').upper() 29 | timestamp = time.strftime("%y%m%d-%H%M%S")+randomnumber 30 | ModelName = 'ExampleScript' 31 | FileName = '%s-%s.tcl'%(ModelName,timestamp) 32 | 33 | Directory = os.getcwd() 34 | OData = OpenSeesAPI.Database.Collector(OpenSeesCommand, Directory+'/tcl/', FileName) 35 | 36 | ########################## Setup and Source Definition ########################## 37 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Initialization')) 38 | OData.AddObject(OpenSeesAPI.Model.BasicBuilder(2,3)) 39 | 40 | ########################## Define Building Geometry, Nodes and Constraints ########################## 41 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Geometry Setup')) 42 | 43 | SupportNode = OData.CreateNode(0,0) 44 | MassNode = OData.CreateNode(0,0) 45 | 46 | ########################## Define Geometric Transformations ########################## 47 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Geometric Transformations')) 48 | 49 | #Define Geometry Transformations for Beams and Column 50 | GeoTransfLinear = OpenSeesAPI.Model.Element.GeomTransf.Linear(1) 51 | OData.AddObject(GeoTransfLinear) 52 | 53 | ############################################################################## 54 | ### All OpenSEES Objects are adding directly to the Database Beyond This Point 55 | ############################################################################## 56 | 57 | ########################## Define Materials and Sections ########################## 58 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Materials and Sections')) 59 | 60 | ########################## Define Rotational Springs for Plastic Hinge ########################## 61 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Rotational Springs for Plastic Hinge')) 62 | 63 | #Define Rotational Spring 64 | #### Collector Should Give ID 65 | 66 | SteelMat = OpenSeesAPI.Model.Element.Material.UniaxialMaterial.Steel01(OData.GetFreeMaterialId(3,1), 78.3, 30000, 0.031) 67 | ConcreteMat = OpenSeesAPI.Model.Element.Material.UniaxialMaterial.Concrete01(OData.GetFreeMaterialId(3,1), -4.35, -0.004, -2.0, -0.014) 68 | 69 | OData.AddMaterial(SteelMat) 70 | OData.AddMaterial(ConcreteMat) 71 | 72 | FiberObjects = [] 73 | FiberObjects.append(OpenSeesAPI.Model.Element.Material.Section.FiberSection.Patch.Rect(ConcreteMat,100,100,0,0,20,40)) 74 | FiberObjects.append(OpenSeesAPI.Model.Element.Material.Section.FiberSection.Layer.Straight(SteelMat,8,1,2,2,18,2)) 75 | FiberObjects.append(OpenSeesAPI.Model.Element.Material.Section.FiberSection.Layer.Straight(SteelMat,8,1,2,38,18,38)) 76 | 77 | FiberSection = OpenSeesAPI.Model.Element.Material.Section.FiberSection(OData.GetFreeElementId(2,1),FiberObjects) 78 | 79 | OData.AddMaterial(FiberSection) 80 | 81 | ########################## Define Elements ########################## 82 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Elements')) 83 | # OData.AddElement(OpenSeesAPI.Model.Element.Element.ZeroLength(OData.GetFreeElementId(9,1),SupportNode, MassNode, [Spring],[1])) 84 | OData.AddElement(OpenSeesAPI.Model.Element.Element.ZeroLengthSection(OData.GetFreeElementId(9,1),SupportNode, MassNode, FiberSection)) 85 | 86 | ############################################################################## 87 | ### Start Writing Elements to the Executible File 88 | ############################################################################## 89 | 90 | # Setting Nodes as Used 91 | for object in set(OData._Elements): 92 | object._NodeI.__setattr__('Used',True) 93 | object._NodeJ.__setattr__('Used',True) 94 | 95 | #Writing Nodes to File 96 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Defining Nodes')) 97 | for obj in OData._Nodes: 98 | try: 99 | if obj.Used: 100 | OData.Executable.AddCommand(obj.CommandLine) 101 | except: 102 | continue 103 | 104 | #Defining Fixity 105 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.Fix(SupportNode,[1,1,1])) 106 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.Fix(MassNode,[0,1,0])) 107 | 108 | #Defining Masses 109 | 110 | #Write Element from OpenSees Collector 111 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Writing Materials')) 112 | for obj in OData._Materials: 113 | OData.Executable.AddCommand(obj.CommandLine) 114 | 115 | #Write Sections from OpenSees Collector 116 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Writing Sections')) 117 | for obj in OData._Sections: 118 | OData.Executable.AddCommand(obj.CommandLine) 119 | 120 | #Write Elements from OpenSees Collector 121 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Writing Elements')) 122 | for obj in OData._Elements: 123 | OData.Executable.AddCommand(obj.CommandLine) 124 | 125 | #Write Shells from OpenSees Collector 126 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Writing Shells')) 127 | for obj in OData._Quadrilaterals: 128 | OData.Executable.AddCommand(obj.CommandLine) 129 | 130 | #Write Constraints from OpenSees Collector 131 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Writing Constraints')) 132 | for obj in OData._Constraints: 133 | OData.Executable.AddCommand(obj.CommandLine) 134 | 135 | ########################## Eigenvalue Analysis ########################## 136 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Eigenvalue Analysis')) 137 | 138 | ########################## Rayleigh Damping ########################## 139 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Rayleigh Damping')) 140 | 141 | ########################## Loads ########################## 142 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Loads')) 143 | 144 | ########################## Time Series ########################## 145 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Time Series')) 146 | 147 | 148 | ########################## Recorders ########################## 149 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Recorder Setup')) 150 | 151 | OutputFolder = 'Results' 152 | 153 | Displacement_File_Name = '%s-NodeD-%s.dat'%(ModelName,timestamp) 154 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Displacement_File_Name, [MassNode], [3], 'disp')) 155 | 156 | Reaction_File_Name = '%s-NodeReact-%s.dat'%(ModelName,timestamp) 157 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Reaction_File_Name, [SupportNode], [3], 'reaction')) 158 | 159 | ########################## Display Results ########################## 160 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Display Results')) 161 | 162 | ########################## Gravity Analysis ########################## 163 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Gravity Analysis')) 164 | 165 | #Load Pattern 166 | GravityLoads = [OpenSeesAPI.Model.Pattern.Load(MassNode,[-200.,0,0])] 167 | OData.AddObject(OpenSeesAPI.Model.Pattern.Plain(100,'Linear', GravityLoads)) #Noticed that my loading and his are different 168 | 169 | #Run Analysis 170 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok 0;')) 171 | OData.AddObject(OpenSeesAPI.Analysis.Integrator.Static.LoadControl(1,1)) 172 | OData.AddObject(OpenSeesAPI.Analysis.Analysis.Static()) 173 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok [analyze 1]')) 174 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('if {$ok == 0} {puts "Gravity Analysis Success"} else { puts "Grsvity Analysis Failed" }')) 175 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('loadConst -time 0.0')) 176 | 177 | ########################## Pushover Analysis ########################## 178 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Pushover Analysis')) 179 | 180 | #Load Pattern 181 | PushOverLoads = [OpenSeesAPI.Model.Pattern.Load(MassNode,[0,0,1])] 182 | OData.AddObject(OpenSeesAPI.Model.Pattern.Plain(200,'Linear', PushOverLoads)) #Noticed that my loading and his are different 183 | 184 | #Define Analysis 185 | OData.AddObject(OpenSeesAPI.Analysis.Constraints.Transformation()) 186 | OData.AddObject(OpenSeesAPI.Analysis.Numberer.RCM()) 187 | # OData.AddObject(OpenSeesAPI.Analysis.System.Mumps(Optional='-ICNTL 50')) 188 | OData.AddObject(OpenSeesAPI.Analysis.System.BandGeneral()) 189 | OData.AddObject(OpenSeesAPI.Analysis.Test.EnergyIncr(1e-4, 10000)) 190 | # OData.AddObject(OpenSeesAPI.Analysis.Test.RelativeNormDispIncr(1e-6,1000)) 191 | OData.AddObject(OpenSeesAPI.Analysis.Algorithm.NewtonLineSearch()) 192 | ControlNode = MassNode 193 | # OData.AddObject(OpenSeesAPI.Analysis.Integrator.Static.DisplacementControl(ControlNode, 1, 0.01)) 194 | # OData.AddObject(OpenSeesAPI.Analysis.Analysis.Static()) 195 | 196 | TargetDrifts = [0,0.01,-0.01,0.01,-0.01,0.02,-0.02,0.02,-0.02,0.04,-0.04,0.04,-0.04, 0.08, -0.08, 0.08, -0.08] 197 | StepSize = 0.0001 198 | LoadingSequence = [] 199 | for i in range(1,len(TargetDrifts),1): 200 | LoadingSequence.extend(list(np.linspace(TargetDrifts[i-1],TargetDrifts[i],int(abs(TargetDrifts[i]-TargetDrifts[i-1])/StepSize)+1))) 201 | LoadingSequence = np.array(LoadingSequence)/100. 202 | 203 | #Run Analysis 204 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok 0;')) 205 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set step 0;')) 206 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set prevDisp 0')) 207 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set Drifts [list %s]'%(''.join(map(lambda x: '%f \t'%(x), LoadingSequence))))) 208 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('foreach targetDisp $Drifts {')) 209 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('integrator DisplacementControl %d 3 [expr $targetDisp-$prevDisp]'%ControlNode._id)) 210 | OData.AddObject(OpenSeesAPI.Analysis.Analysis.Static()) 211 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok [analyze 1]')) 212 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('puts "Running Push Over Step: $step"')) 213 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('incr step')) 214 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set prevDisp $targetDisp')) 215 | # OData.AddObject(OpenSeesAPI.TCL.TCLScript('puts "Not Ok Doing Other Stuff')) 216 | 217 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('}')) 218 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('if {$ok == 0} {puts "Analysis Success"} else { puts "Analysis Failed" }')) 219 | 220 | ########################## Time History Analysis ########################## 221 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Time History Analysis')) 222 | 223 | ########################## Close File ########################## 224 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Close File')) 225 | 226 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('wipe al b l;')) 227 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('puts "Models Run Complete";')) 228 | 229 | ############################################################################## 230 | ### Start Running OpenSees File 231 | ############################################################################## 232 | 233 | ########################## Plot Geometry ########################## 234 | 235 | ########################## Run OpenSees Script ########################## 236 | OData.Executable.StartAnalysis(SuppressOutput=False) 237 | 238 | ########################## Load Result Files ########################## 239 | Displ = np.loadtxt(Directory+'/tcl/'+OutputFolder+'/'+Displacement_File_Name) 240 | Reac = np.loadtxt(Directory+'/tcl/'+OutputFolder+'/'+Reaction_File_Name) 241 | 242 | ########################## Removing Files ########################## 243 | 244 | try: 245 | os.remove(Directory+'/tcl/%s-%s.out'%(ModelName,timestamp)) 246 | except: 247 | pass 248 | 249 | os.remove(Directory+'/tcl/%s-%s.tcl'%(ModelName,timestamp)) 250 | os.remove(Directory+'/tcl/'+OutputFolder+'/'+Displacement_File_Name) 251 | os.remove(Directory+'/tcl/'+OutputFolder+'/'+Reaction_File_Name) 252 | 253 | ########################## Plot Push Over ########################## 254 | 255 | import matplotlib.pylab as plt 256 | plt.figure(figsize=(4,4)) 257 | plt.plot(Displ[1:,1], Reac[1:, 1]) 258 | plt.xlabel('Curvature'); plt.ylabel('Moment, k-in') 259 | plt.grid() 260 | plt.show() -------------------------------------------------------------------------------- /test/SampleScript4.py: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | ##### This is a sample script that runs a Dynamic Steel Moment Frame analysis in OpenSees 3 | ##### using an Ibarra-Krawinkler Deterioation spring 4 | ##### Coded by Nasser Marafi (marafi@uw.edu) 5 | ##### Last Updated: 2/19/2016 6 | ############################################################################ 7 | __author__ = 'marafi' 8 | 9 | import os 10 | import numpy as np 11 | 12 | ########################## Input Parameters ########################## 13 | 14 | # This is Elcentro's Ground Motion in g 15 | GMData = 1.90*386.2*np.array([0.0063,0.00364,0.00099,0.00428,0.00758,0.01087,0.00682,0.00277,-0.00128,0.00368,0.00864,0.0136,0.00727,0.00094,0.0042,0.00221,0.00021,0.00444,0.00867,0.0129,0.01713,-0.00343,-0.024,-0.00992,0.00416,0.00528,0.01653,0.02779,0.03904,0.02449,0.00995,0.00961,0.00926,0.00892,-0.00486,-0.01864,-0.03242,-0.03365,-0.05723,-0.04534,-0.03346,-0.03201,-0.03056,-0.02911,-0.02766,-0.04116,-0.05466,-0.06816,-0.08166,-0.06846,-0.05527,-0.04208,-0.04259,-0.04311,-0.02428,-0.00545,0.01338,0.03221,0.05104,0.06987,0.0887,0.04524,0.00179,-0.04167,-0.08513,-0.12858,-0.17204,-0.12908,-0.08613,-0.08902,-0.09192,-0.09482,-0.09324,-0.09166,-0.09478,-0.09789,-0.12902,-0.07652,-0.02401,0.02849,0.08099,0.1335,0.186,0.2385,0.21993,0.20135,0.18277,0.1642,0.14562,0.16143,0.17725,0.13215,0.08705,0.04196,-0.00314,-0.04824,-0.09334,-0.13843,-0.18353,-0.22863,-0.27372,-0.31882,-0.25024,-0.18166,-0.11309,-0.04451,0.02407,0.09265,0.16123,0.22981,0.29839,0.23197,0.16554,0.09912,0.0327,-0.03372,-0.10014,-0.16656,-0.23299,-0.29941,-0.00421,0.29099,0.2238,0.15662,0.08943,0.02224,-0.04495,0.01834,0.08163,0.14491,0.2082,0.18973,0.17125,0.13759,0.10393,0.07027,0.03661,0.00295,-0.03071,-0.00561,0.01948,0.04458,0.06468,0.08478,0.10487,0.05895,0.01303,-0.03289,-0.07882,-0.03556,0.00771,0.05097,0.01013,-0.03071,-0.07156,-0.1124,-0.15324,-0.11314,-0.07304,-0.03294,0.00715,-0.0635,-0.13415,-0.2048,-0.12482,-0.04485,0.03513,0.1151,0.19508,0.12301,0.05094,-0.02113,-0.0932,-0.02663,0.03995,0.10653,0.17311,0.11283,0.05255,-0.00772,0.01064,0.029,0.04737,0.06573,0.02021,-0.0253,-0.07081,-0.04107,-0.01133,0.00288,0.01709,0.03131,-0.02278,-0.07686,-0.13095,-0.18504,-0.14347,-0.1019,-0.06034,-0.01877,0.0228,-0.00996,-0.04272,-0.02147,-0.00021,0.02104,-0.01459,-0.05022,-0.08585,-0.12148,-0.15711,-0.19274,-0.22837,-0.18145,-0.13453,-0.08761,-0.04069,0.00623,0.05316,0.10008,0.147,0.09754,0.04808,-0.00138,0.05141,0.1042,0.15699,0.20979,0.26258,0.16996,0.07734,-0.01527,-0.10789,-0.20051,-0.06786,0.06479,0.01671,-0.03137,-0.07945,-0.12753,-0.17561,-0.22369,-0.27177,-0.15851,-0.04525,0.06802,0.18128,0.14464,0.108,0.07137,0.03473,0.09666,0.1586,0.22053,0.18296,0.14538,0.1078,0.07023,0.03265,0.06649,0.10033,0.13417,0.10337,0.07257,0.04177,0.01097,-0.01983,0.04438,0.1086,0.17281,0.10416,0.03551,-0.03315,-0.1018,-0.07262,-0.04344,-0.01426,0.01492,-0.02025,-0.05543,-0.0906,-0.12578,-0.16095,-0.19613,-0.14784,-0.09955,-0.05127,-0.00298,-0.01952,-0.03605,-0.05259,-0.04182,-0.03106,-0.02903,-0.02699,0.02515,0.0177,0.02213,0.02656,0.00419,-0.01819,-0.04057,-0.06294,-0.02417,0.0146,0.05337,0.02428,-0.0048,-0.03389,-0.00557,0.02274,0.00679,-0.00915,-0.02509,-0.04103,-0.05698,-0.01826,0.02046,0.00454,-0.01138,-0.00215,0.00708,0.00496,0.00285,0.00074,-0.00534,-0.01141,0.00361,0.01863,0.03365,0.04867,0.0304,0.01213,-0.00614,-0.02441,0.01375,0.01099,0.00823,0.00547,0.00812,0.01077,-0.00692,-0.02461,-0.0423,-0.05999,-0.07768,-0.09538,-0.06209,-0.0288,0.00448,0.03777,0.01773,-0.00231,-0.02235,0.01791,0.05816,0.03738,0.0166,-0.00418,-0.02496,-0.04574,-0.02071,0.00432,0.02935,0.01526,0.01806,0.02086,0.00793,-0.00501,-0.01795,-0.03089,-0.01841,-0.00593,0.00655,-0.02519,-0.05693,-0.04045,-0.02398,-0.0075,0.00897,0.00384,-0.00129,-0.00642,-0.01156,-0.02619,-0.04082,-0.05545,-0.04366,-0.03188,-0.06964,-0.05634,-0.04303,-0.02972,-0.01642,-0.00311,0.0102,0.0235,0.03681,0.05011,0.02436,-0.00139,-0.02714,-0.00309,0.02096,0.04501,0.06906,0.05773,0.0464,0.03507,0.03357,0.03207,0.03057,0.0325,0.03444,0.03637,0.01348,-0.00942,-0.03231,-0.02997,-0.03095,-0.03192,-0.02588,-0.01984,-0.01379,-0.00775,-0.01449,-0.02123,0.01523,0.0517,0.08816,0.12463,0.16109,0.12987,0.09864,0.06741,0.03618,0.00495,0.0042,0.00345,0.00269,-0.05922,-0.12112,-0.18303,-0.12043,-0.05782,0.00479,0.0674,0.13001,0.08373,0.03745,0.06979,0.10213,-0.03517,-0.17247,-0.13763,-0.10278,-0.06794,-0.0331,-0.03647,-0.03984,-0.00517,0.0295,0.06417,0.09883,0.1335,0.05924,-0.01503,-0.08929,-0.16355,-0.06096,0.04164,0.01551,-0.01061,-0.03674,-0.06287,-0.08899,-0.0543,-0.01961,0.01508,0.04977,0.08446,0.05023,0.016,-0.01823,-0.05246,-0.08669,-0.06769,-0.0487,-0.0297,-0.01071,0.00829,-0.00314,0.02966,0.06246,-0.00234,-0.06714,-0.04051,-0.01388,0.01274,0.00805,0.03024,0.05243,0.02351,-0.00541,-0.03432,-0.06324,-0.09215,-0.12107,-0.0845,-0.04794,-0.01137,0.0252,0.06177,0.04028,0.0188,0.04456,0.07032,0.09608,0.12184,0.0635,0.00517,-0.05317,-0.03124,-0.0093,0.01263,0.03457,0.03283,0.03109,0.02935,0.04511,0.06087,0.07663,0.09239,0.05742,0.02245,-0.01252,0.0068,0.02611,0.04543,0.01571,-0.01402,-0.04374,-0.07347,-0.0399,-0.00633,0.02724,0.0608,0.03669,0.01258,-0.01153,-0.03564,-0.00677,0.0221,0.05098,0.07985,0.06915,0.05845,0.04775,0.03706,0.02636,0.05822,0.09009,0.12196,0.10069,0.07943,0.05816,0.03689,0.01563,-0.00564,-0.0269,-0.04817,-0.06944,-0.0907,-0.11197,-0.11521,-0.11846,-0.1217,-0.12494,-0.165,-0.20505,-0.15713,-0.10921,-0.06129,-0.01337,0.03455,0.08247,0.07576,0.06906,0.06236,0.08735,0.11235,0.13734,0.12175,0.10616,0.09057,0.07498,0.08011,0.08524,0.09037,0.06208,0.03378,0.00549,-0.02281,-0.05444,-0.0403,-0.02615,-0.01201,-0.02028,-0.02855,-0.06243,-0.03524,-0.00805,-0.04948,-0.03643,-0.02337,-0.03368,-0.01879,-0.00389,0.011,0.02589,0.01446,0.00303,-0.0084,0.00463,0.01766,0.03069,0.04372,0.02165,-0.00042,-0.02249,-0.04456,-0.03638,-0.02819,-0.02001,-0.01182,-0.02445,-0.03707,-0.04969,-0.05882,-0.06795,-0.07707,-0.0862,-0.09533,-0.06276,-0.03018,0.00239,0.03496,0.04399,0.05301,0.03176,0.01051,-0.01073,-0.03198,-0.05323,0.00186,0.05696,0.01985,-0.01726,-0.05438,-0.01204,0.03031,0.07265,0.11499,0.07237,0.02975,-0.01288,0.01212,0.03711,0.03517,0.03323,0.01853,0.00383,0.00342,-0.02181,-0.04704,-0.07227,-0.0975,-0.12273,-0.08317,-0.04362,-0.00407,0.03549,0.07504,0.1146,0.07769,0.04078,0.00387,0.00284,0.00182,-0.05513,0.04732,0.05223,0.05715,0.06206,0.06698,0.07189,0.02705,-0.01779,-0.06263,-0.10747,-0.15232,-0.12591,-0.0995,-0.07309,-0.04668,-0.02027,0.00614,0.03255,0.00859,-0.01537,-0.03932,-0.06328,-0.03322,-0.00315,0.02691,0.01196,-0.003,0.00335,0.0097,0.01605,0.02239,0.04215,0.06191,0.08167,0.03477,-0.01212,-0.01309,-0.01407,-0.05274,-0.02544,0.00186,0.02916,0.05646,0.08376,0.01754,-0.04869,-0.02074,0.00722,0.03517,-0.00528,-0.04572,-0.08617,-0.0696,-0.05303,-0.03646,-0.01989,-0.00332,0.01325,0.02982,0.01101,-0.00781,-0.02662,-0.00563,0.01536,0.03635,0.05734,0.03159,0.00584,-0.01992,-0.00201,0.01589,-0.01024,-0.03636,-0.06249,-0.0478,-0.03311,-0.04941,-0.0657,-0.082,-0.0498,-0.0176,0.0146,0.0468,0.079,0.0475,0.016,-0.0155,-0.00102,0.01347,0.02795,0.04244,0.05692,0.03781,0.0187,-0.00041,-0.01952,-0.00427,0.01098,0.02623,0.04148,0.01821,-0.00506,-0.00874,-0.03726,-0.06579,-0.026,0.0138,0.05359,0.09338,0.05883,0.02429,-0.01026,-0.0448,-0.01083,-0.01869,-0.02655,-0.03441,-0.02503,-0.01564,-0.00626,-0.01009,-0.01392,0.0149,0.04372,0.03463,0.02098,0.00733,-0.00632,-0.01997,0.00767,0.03532,0.03409,0.03287,0.03164,0.02403,0.01642,0.00982,0.00322,-0.00339,0.02202,-0.01941,-0.06085,-0.10228,-0.07847,-0.05466,-0.03084,-0.00703,0.01678,0.01946,0.02214,0.02483,0.01809,-0.00202,-0.02213,-0.00278,0.01656,0.0359,0.05525,0.07459,0.06203,0.04948,0.03692,-0.00145,0.04599,0.04079,0.03558,0.03037,0.03626,0.04215,0.04803,0.05392,0.04947,0.04502,0.04056,0.03611,0.03166,0.00614,-0.01937,-0.04489,-0.0704,-0.09592,-0.07745,-0.05899,-0.04052,-0.02206,-0.00359,0.01487,0.01005,0.00523,0.00041,-0.00441,-0.00923,-0.01189,-0.01523,-0.01856,-0.0219,-0.00983,0.00224,0.01431,0.00335,-0.0076,-0.01856,-0.00737,0.00383,0.01502,0.02622,0.01016,-0.0059,-0.02196,-0.00121,0.01953,0.04027,0.02826,0.01625,0.00424,0.00196,-0.00031,-0.00258,-0.00486,-0.00713,-0.00941,-0.01168,-0.01396,-0.0175,-0.02104,-0.02458,-0.02813,-0.03167,-0.03521,-0.04205,-0.04889,-0.03559,-0.02229,-0.00899,0.00431,0.01762,0.00714,-0.00334,-0.01383,0.01314,0.04011,0.06708,0.0482,0.02932,0.01043,-0.00845,-0.02733,-0.04621,-0.03155,-0.01688,-0.00222,0.01244,0.02683,0.04121,0.05559,0.03253,0.00946,-0.0136,-0.01432,-0.01504,-0.01576,-0.04209,-0.02685,-0.01161,0.00363,0.01887,0.03411,0.03115,0.02819,0.02917,0.03015,0.03113,0.00388,-0.02337,-0.05062,-0.0382,-0.02579,-0.01337,-0.00095,0.01146,0.02388,0.03629,0.01047,-0.01535,-0.04117,-0.06699,-0.05207,-0.03715,-0.02222,-0.0073,0.00762,0.02254,0.03747,0.04001,0.04256,0.04507,0.04759,0.0501,0.04545,0.0408,0.02876,0.01671,0.00467,-0.00738,-0.00116,0.00506,0.01128,0.0175,-0.00211,-0.02173,-0.04135,-0.06096,-0.08058,-0.06995,-0.05931,-0.04868,-0.03805,-0.02557,-0.0131,-0.00063,0.01185,0.02432,0.0368,0.04927,0.02974,0.01021,-0.00932,-0.02884,-0.04837,-0.0679,-0.04862,-0.02934,-0.01006,0.00922,0.02851,0.04779,0.02456,0.00133,-0.0219,-0.04513,-0.06836,-0.04978,-0.0312,-0.01262,0.00596,0.02453,0.04311,0.06169,0.08027,0.09885,0.06452,0.03019,-0.00414,-0.03848,-0.07281,-0.05999,-0.04717,-0.03435,-0.03231,-0.03028,-0.02824,-0.00396,0.02032,0.00313,-0.01406,-0.03124,-0.04843,-0.06562,-0.05132,-0.03702,-0.02272,-0.00843,0.00587,0.02017,0.02698,0.03379,0.04061,0.04742,0.05423,0.03535,0.01647,0.01622,0.01598,0.01574,0.00747,-0.0008,-0.00907,0.00072,0.01051,0.0203,0.03009,0.03989,0.03478,0.02967,0.02457,0.03075,0.03694,0.04313,0.04931,0.0555,0.06168,-0.00526,-0.0722,-0.06336,-0.05451,-0.04566,-0.03681,-0.03678,-0.03675,-0.03672,-0.01765,0.00143,0.02051,0.03958,0.05866,0.03556,0.01245,-0.01066,-0.03376,-0.05687,-0.04502,-0.03317,-0.02131,-0.00946,0.00239,-0.00208,-0.00654,-0.01101,-0.01548,-0.012,-0.00851,-0.00503,-0.00154,0.00195,0.00051,-0.00092,0.01135,0.02363,0.0359,0.04818,0.06045,0.07273,0.02847,-0.01579,-0.06004,-0.05069,-0.04134,-0.03199,-0.03135,-0.03071,-0.03007,-0.01863,-0.00719,0.00425,0.0157,0.02714,0.03858,0.02975,0.02092,0.02334,0.02576,0.02819,0.03061,0.03304,0.01371,-0.00561,-0.02494,-0.02208,-0.01923,-0.01638,-0.01353,-0.01261,-0.0117,-0.00169,0.00833,0.01834,0.02835,0.03836,0.04838,0.03749,0.0266,0.01571,0.00482,-0.00607,-0.01696,-0.0078,0.00136,0.01052,0.01968,0.02884,-0.00504,-0.03893,-0.02342,-0.00791,0.00759,0.0231,0.00707,-0.00895,-0.02498,-0.041,-0.05703,-0.0292,-0.00137,0.02645,0.05428,0.03587,0.01746,-0.00096,-0.01937,-0.03778,-0.02281,-0.00784,0.00713,0.0221,0.03707,0.05204,0.06701,0.08198,0.03085,-0.02027,-0.0714,-0.12253,-0.08644,-0.05035,-0.01426,0.02183,0.05792,0.094,0.13009,0.03611,-0.05787,-0.04802,-0.03817,-0.02832,-0.01846,-0.00861,-0.03652,-0.06444,-0.06169,-0.05894,-0.05618,-0.06073,-0.06528,-0.04628,-0.02728,-0.00829,0.01071,0.0297,0.03138,0.03306,0.03474,0.03642,0.04574,0.05506,0.06439,0.07371,0.08303,0.03605,-0.01092,-0.0579,-0.04696,-0.03602,-0.02508,-0.01414,-0.03561,-0.05708,-0.07855,-0.06304,-0.04753,-0.03203,-0.01652,-0.00102,0.00922,0.01946,0.0297,0.03993,0.05017,0.06041,0.07065,0.08089,-0.00192,-0.08473,-0.07032,-0.0559,-0.04148,-0.05296,-0.06443,-0.0759,-0.08738,-0.09885,-0.06798,-0.0371,-0.00623,0.02465,0.05553,0.0864,0.11728,0.14815,0.08715,0.02615,-0.03485,-0.09584,-0.071,-0.04616,-0.02132,0.00353,0.02837,0.05321,-0.00469,-0.06258,-0.12048,-0.0996,-0.07872,-0.05784,-0.03696,-0.01608,0.0048,0.02568,0.04656,0.06744,0.08832,0.1092,0.13008,0.10995,0.08982,0.06969,0.04955,0.04006,0.03056,0.02107,0.01158,0.0078,0.00402,0.00024,-0.00354,-0.00732,-0.0111,-0.0078,-0.0045,-0.0012,0.0021,0.0054,-0.00831,-0.02203,-0.03575,-0.04947,-0.06319,-0.05046,-0.03773,-0.025,-0.01227,0.00046,0.00482,0.00919,0.01355,0.01791,0.02228,0.00883,-0.00462,-0.01807,-0.03152,-0.02276,-0.01401,-0.00526,0.0035,0.01225,0.02101,0.01437,0.00773,0.0011,0.00823,0.01537,0.02251,0.01713,0.01175,0.00637,0.01376,0.02114,0.02852,0.03591,0.04329,0.03458,0.02587,0.01715,0.00844,-0.00027,-0.00898,-0.00126,0.00645,0.01417,0.02039,0.02661,0.03283,0.03905,0.04527,0.03639,0.0275,0.01862,0.00974,0.00086,-0.01333,-0.02752,-0.04171,-0.02812,-0.01453,-0.00094,0.01264,0.02623,0.0169,0.00756,-0.00177,-0.01111,-0.02044,-0.02977,-0.03911,-0.02442,-0.00973,0.00496,0.01965,0.03434,0.02054,0.00674,-0.00706,-0.02086,-0.03466,-0.02663,-0.0186,-0.01057,-0.00254,-0.00063,0.00128,0.00319,0.0051,0.00999,0.01488,0.00791,0.00093,-0.00605,0.00342,0.01288,0.02235,0.03181,0.04128,0.02707,0.01287,-0.00134,-0.01554,-0.02975,-0.04395,-0.03612,-0.02828,-0.02044,-0.0126,-0.00476,0.00307,0.01091,0.00984,0.00876,0.00768,0.00661,0.01234,0.01807,0.0238,0.02953,0.03526,0.02784,0.02042,0.013,-0.03415,-0.00628,-0.00621,-0.00615,-0.00609,-0.00602,-0.00596,-0.0059,-0.00583,-0.00577,-0.00571,-0.00564,-0.00558,-0.00552,-0.00545,-0.00539,-0.00532,-0.00526,-0.0052,-0.00513,-0.00507,-0.00501,-0.00494,-0.00488,-0.00482,-0.00475,-0.00469,-0.00463,-0.00456,-0.0045,-0.00444,-0.00437,-0.00431,-0.00425,-0.00418,-0.00412,-0.00406,-0.00399,-0.00393,-0.00387,-0.0038,-0.00374,-0.00368,-0.00361,-0.00355,-0.00349,-0.00342,-0.00336,-0.0033,-0.00323,-0.00317,-0.00311,-0.00304,-0.00298,-0.00292,-0.00285,-0.00279,-0.00273,-0.00266,-0.0026,-0.00254,-0.00247,-0.00241,-0.00235,-0.00228,-0.00222,-0.00216,-0.00209,-0.00203,-0.00197,-0.0019,-0.00184,-0.00178,-0.00171,-0.00165,-0.00158,-0.00152,-0.00146,-0.00139,-0.00133,-0.00127,-0.0012,-0.00114,-0.00108,-0.00101,-0.00095,-0.00089,-0.00082,-0.00076,-0.0007,-0.00063,-0.00057,-0.00051,-0.00044,-0.00038,-0.00032,-0.00025,-0.00019,-0.00013,-0.00006,0]+list(np.zeros(1000))) 16 | Dt = 0.02 17 | 18 | OpenSeesCommand = 'OpenSees' 19 | 20 | ########################## Pre-Initialization ########################## 21 | import OpenSeesAPI 22 | import os 23 | import numpy as np 24 | 25 | ########################## Initializing ########################## 26 | 27 | ### Create OpenSees Database 28 | 29 | import uuid 30 | randomnumber = str(uuid.uuid4()).replace('-','').upper() 31 | ModelName = 'SteelMomentFrame' 32 | FileName = '%s.tcl'%(ModelName) 33 | TCLFileDirectory = os.getcwd()+'/tcl/' 34 | ResultDirectory = os.getcwd()+'/tcl/Results/' 35 | 36 | if not os.path.exists(TCLFileDirectory): #Make Directory is unavailable 37 | os.makedirs(TCLFileDirectory) 38 | if not os.path.exists(ResultDirectory): #Make Directory is unavailable 39 | os.makedirs(ResultDirectory) 40 | 41 | OData = OpenSeesAPI.Database.Collector(OpenSeesCommand, TCLFileDirectory, FileName) 42 | 43 | ########################## Setup and Source Definition ########################## 44 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Initialization')) 45 | OData.AddObject(OpenSeesAPI.Model.BasicBuilder(2,3)) 46 | 47 | ########################## Define Building Geometry, Nodes and Constraints ########################## 48 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Geometry Setup')) 49 | 50 | # Create Grid Line Arrays 51 | XGrids = [0, 30.*12, 45.*12] 52 | YGrids = [0, 15.*12, 27.*12] 53 | 54 | FloorMass = np.array([0, 535., 525.])/386.2 #in Kips 55 | 56 | # Create Main Grid Nodes 57 | for i in range(len(XGrids)): 58 | for j in range(len(YGrids)): 59 | OData.CreateNode(XGrids[i], YGrids[j], GridX=i, GridY=j) 60 | 61 | ########################## Define Geometric Transformations ########################## 62 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Geometric Transformations')) 63 | 64 | #Define Geometry Transformations for Beams and Column 65 | GeoTransfLinear = OpenSeesAPI.Model.Element.GeomTransf.Linear(1) 66 | GeoTransfPDelta = OpenSeesAPI.Model.Element.GeomTransf.PDelta(2) 67 | OData.AddObject(GeoTransfLinear) 68 | OData.AddObject(GeoTransfPDelta) 69 | 70 | ############################################################################## 71 | ### All OpenSEES Objects are adding directly to the Database Beyond This Point 72 | ############################################################################## 73 | 74 | ########################## Define Materials and Sections ########################## 75 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Materials, Sections and Elements')) 76 | 77 | #Create Columns - Element Type 5 78 | def CreateColumn(XGrid, YGrid): #YGrid must be more than 0 79 | n = 10. 80 | E = 29000. 81 | Acol = 38.5 82 | Icol = 4020*(1.+n)/n 83 | Mycol = 20350. 84 | Lambda = 1000. 85 | ThetaP = 0.025 86 | ThetaPC = 0.3 87 | Kappa = 0.4 88 | 89 | Ks = 6.0*E*Icol/(YGrids[YGrid]-YGrids[YGrid-1])*n 90 | a_mem = (n+1)*(Mycol*0.05)/(Ks*ThetaP) 91 | Alpha = a_mem/(1.+n*(1.0-a_mem)) 92 | 93 | #Get and Create Sub Nodes for the Zero Length Elements 94 | BaseNode = OData.GetNodesByGrid(XGrid,YGrid-1)[0] 95 | BaseSubNode = OData.CreateNode(XGrids[XGrid],YGrids[YGrid-1],NodeType=2,GridX=XGrid,GridY=YGrid-1) 96 | TopNode = OData.GetNodesByGrid(XGrid,YGrid)[0] 97 | TopSubNode = OData.CreateNode(XGrids[XGrid],YGrids[YGrid],NodeType=2,GridX=XGrid,GridY=YGrid) 98 | 99 | Mat = OData.AddMaterial(OpenSeesAPI.Model.Element.Material.UniaxialMaterial.Bilin(OData.GetFreeMaterialId(1,1), Ks, Alpha, Alpha, Mycol, -1*Mycol, Lambda, Lambda, Lambda, Lambda, 1, 1, 1, 1, ThetaP, ThetaP, ThetaPC, ThetaPC, Kappa, Kappa, 1.0, 1.0, 1.0, 1.0)) 100 | OData.AddElement(OpenSeesAPI.Model.Element.Element.ZeroLength(OData.GetFreeElementId(9,1), BaseNode, BaseSubNode, [Mat], [3])) 101 | OData.AddElement(OpenSeesAPI.Model.Element.Element.ZeroLength(OData.GetFreeElementId(9,1), TopSubNode, TopNode, [Mat], [3])) 102 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.EqualDOF(BaseNode,BaseSubNode,[1,2])) 103 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.EqualDOF(TopNode,TopSubNode,[1,2])) 104 | OData.AddElement(OpenSeesAPI.Model.Element.Element.ElasticBeamColumn(OData.GetFreeElementId(5,1), BaseSubNode, TopSubNode, Acol, E, Icol, GeoTransfPDelta)) 105 | 106 | CreateColumn(0,1) 107 | CreateColumn(1,1) 108 | CreateColumn(0,2) 109 | CreateColumn(1,2) 110 | 111 | #Create Beams - Element Type 6 112 | def CreateBeam(StartXGrid, EndXGrid, YGrid): #YGrid must be more than 0 113 | n = 10. 114 | E = 29000. 115 | Abeam = 30. 116 | Ibeam = 3620.*(n+1)/n 117 | Mybeam = 10938. 118 | Lambda = 1000. 119 | ThetaP = 0.02 120 | ThetaPC = 0.16 121 | Kappa = 0.4 122 | 123 | Ks = 6.0*E*Ibeam/(XGrids[EndXGrid]-XGrids[StartXGrid])*n 124 | a_mem = (n+1)*(Mybeam*0.05)/(Ks*ThetaP) 125 | Alpha = a_mem/(1.+n*(1.0-a_mem)) 126 | 127 | #Get and Create Sub Nodes for the Zero Length Elements 128 | StartNode = OData.GetNodesByGrid(StartXGrid,YGrid)[0] 129 | StartSubNode = OData.CreateNode(XGrids[StartXGrid],YGrids[YGrid],NodeType=2,GridX=StartXGrid,GridY=YGrid) 130 | EndNode = OData.GetNodesByGrid(EndXGrid,YGrid)[0] 131 | EndSubNode = OData.CreateNode(XGrids[EndXGrid],YGrids[YGrid],NodeType=2,GridX=EndXGrid,GridY=YGrid) 132 | 133 | Mat = OData.AddMaterial(OpenSeesAPI.Model.Element.Material.UniaxialMaterial.Bilin(OData.GetFreeMaterialId(1,1), Ks, Alpha, Alpha, Mybeam, -1*Mybeam, Lambda, Lambda, Lambda, Lambda, 1, 1, 1, 1, ThetaP, ThetaP, ThetaPC, ThetaPC, Kappa, Kappa, 1.0, 1.0, 1.0, 1.0)) 134 | OData.AddElement(OpenSeesAPI.Model.Element.Element.ZeroLength(OData.GetFreeElementId(9,1), StartNode, StartSubNode, [Mat], [3])) 135 | OData.AddElement(OpenSeesAPI.Model.Element.Element.ZeroLength(OData.GetFreeElementId(9,1), EndNode, EndSubNode, [Mat], [3])) 136 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.EqualDOF(StartNode,StartSubNode,[1,2])) 137 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.EqualDOF(EndNode,EndSubNode,[1,2])) 138 | OData.AddElement(OpenSeesAPI.Model.Element.Element.ElasticBeamColumn(OData.GetFreeElementId(6,1), StartSubNode,EndSubNode, Abeam, E, Ibeam, GeoTransfPDelta)) 139 | 140 | CreateBeam(0,1,1) 141 | CreateBeam(0,1,2) 142 | 143 | # Add PDelta Column and Truss Element 144 | BasePDNode = OData.GetNodesByGrid(2,0,NodeType=1)[0] 145 | FirstStoryPDNode = OData.GetNodesByGrid(2,1,NodeType=1)[0] 146 | SecondStoryPDNode = OData.GetNodesByGrid(2,2,NodeType=1)[0] 147 | 148 | FirstStoryMainStructureNode = OData.GetNodesByGrid(1,1,NodeType=1)[0] 149 | SecondStoryMainStructureNode = OData.GetNodesByGrid(1,2,NodeType=1)[0] 150 | 151 | OData.AddElement(OpenSeesAPI.Model.Element.Element.ElasticBeamColumn(OData.GetFreeElementId(8,1),BasePDNode,FirstStoryPDNode,1e6, 1e6, 1e2, GeoTransfPDelta)) 152 | OData.AddElement(OpenSeesAPI.Model.Element.Element.ElasticBeamColumn(OData.GetFreeElementId(8,1),FirstStoryPDNode,SecondStoryPDNode,1e6, 1e6, 1e2, GeoTransfPDelta)) 153 | Mat = OData.AddMaterial(OpenSeesAPI.Model.Element.Material.UniaxialMaterial.Elastic(OData.GetFreeMaterialId(1,1), 29000.)) 154 | OData.AddElement(OpenSeesAPI.Model.Element.Element.Truss(OData.GetFreeElementId(8,1), FirstStoryMainStructureNode, FirstStoryPDNode, 1e6, Mat)) 155 | OData.AddElement(OpenSeesAPI.Model.Element.Element.Truss(OData.GetFreeElementId(8,1), SecondStoryMainStructureNode, SecondStoryPDNode, 1e6, Mat)) 156 | 157 | ############################################################################## 158 | ### Start Writing Elements to the Executible File 159 | ############################################################################## 160 | 161 | # Setting Nodes as Used (sometimes you make a lot of nodes which you don't use) 162 | for object in set(OData._Elements): 163 | object._NodeI.__setattr__('Used',True) 164 | object._NodeJ.__setattr__('Used',True) 165 | 166 | #Writing Nodes to File 167 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Defining Nodes')) 168 | for obj in OData._Nodes: 169 | try: 170 | if obj.Used: 171 | OData.Executable.AddCommand(obj.CommandLine) 172 | except: 173 | continue 174 | 175 | #Defining Fixity 176 | BaseNode1 = OData.GetNodesByGrid(0,0,NodeType=1)[0] 177 | BaseNode2 = OData.GetNodesByGrid(1,0,NodeType=1)[0] 178 | BaseNode3 = OData.GetNodesByGrid(2,0,NodeType=1)[0] 179 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.Fix(BaseNode1,[1,1,1])) 180 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.Fix(BaseNode2,[1,1,1])) 181 | OData.AddConstraint(OpenSeesAPI.Model.Constraint.Fix(BaseNode3,[1,1,0])) 182 | 183 | #Defining Masses 184 | 185 | for j in range(1,len(YGrids)): 186 | for i in range(len(XGrids)-1): 187 | for node in OData.GetNodesByGrid(i,j): 188 | OData.AddObject(OpenSeesAPI.Model.Node.Mass(node, [FloorMass[j]/2., 1.e-6, 1.e-6])) 189 | 190 | #Write Element from OpenSees Collector 191 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Writing Materials')) 192 | for obj in OData._Materials: 193 | OData.Executable.AddCommand(obj.CommandLine) 194 | 195 | #Write Sections from OpenSees Collector 196 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Writing Sections')) 197 | for obj in OData._Sections: 198 | OData.Executable.AddCommand(obj.CommandLine) 199 | 200 | #Write Elements from OpenSees Collector 201 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Writing Elements')) 202 | for obj in OData._Elements: 203 | OData.Executable.AddCommand(obj.CommandLine) 204 | 205 | #Write Shells from OpenSees Collector 206 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Writing Shells')) 207 | for obj in OData._Quadrilaterals: 208 | OData.Executable.AddCommand(obj.CommandLine) 209 | 210 | #Write Constraints from OpenSees Collector 211 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Writing Constraints')) 212 | for obj in OData._Constraints: 213 | OData.Executable.AddCommand(obj.CommandLine) 214 | 215 | ########################## Eigenvalue Analysis ########################## 216 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Eigenvalue Analysis')) 217 | OData.AddObject(OpenSeesAPI.Analysis.Eigen(1, fullGenLapack=True)) 218 | 219 | ########################## Rayleigh Damping ########################## 220 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Rayleigh Damping')) 221 | # Adding Rayleigh Damping to the Mass Matrix Only 222 | T = 0.82 223 | Zeta = 0.05 224 | OData.AddObject(OpenSeesAPI.Model.Node.Rayleigh(2 * Zeta * 2 * np.pi / T, 0, 0, 0)) 225 | 226 | ########################## Loads ########################## 227 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Loads')) 228 | 229 | Loads = [] 230 | for i in range(1,len(YGrids)): 231 | Node = OData.GetNodesByGrid(2,i)[0] 232 | Loads.append(OpenSeesAPI.Model.Pattern.Load(Node,[0, -1*FloorMass[i]*386.2, 0])) 233 | 234 | OData.AddObject(OpenSeesAPI.Model.Pattern.Plain(100,'Linear',Loads)) 235 | 236 | ########################## Time Series ########################## 237 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Time Series')) 238 | 239 | TimeSeries = OpenSeesAPI.Model.TimeSeries.Path(1,Dt, GMData) 240 | OData.AddObject(TimeSeries) 241 | 242 | ########################## Recorders ########################## 243 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Recorder Setup')) 244 | 245 | OutputFolder = 'Results' 246 | 247 | Displacement_File_Name = '%s-NodeD.dat'%(ModelName) 248 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Displacement_File_Name, [SecondStoryMainStructureNode], [1], 'disp')) 249 | 250 | Velocity_File_Name = '%s-NodeV.dat'%(ModelName) 251 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Velocity_File_Name, [SecondStoryMainStructureNode], [1], 'vel')) 252 | 253 | Acceleration_File_Name = '%s-NodeA.dat'%(ModelName) 254 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Acceleration_File_Name, [SecondStoryMainStructureNode], [1], 'accel','-timeSeries %d'%TimeSeries.id)) 255 | 256 | Reaction_File_Name = '%s-NodeReact.dat'%(ModelName) 257 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Reaction_File_Name, OData.GetNodesByYGrid(0, NodeType=1), [1], 'reaction')) 258 | 259 | ########################## Display Results ########################## 260 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Display Results')) 261 | 262 | ########################## Gravity Analysis ########################## 263 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Gravity Analysis')) 264 | 265 | NoOfGravitySteps = 1 266 | OData.AddObject(OpenSeesAPI.Analysis.Constraints.Transformation()) 267 | OData.AddObject(OpenSeesAPI.Analysis.Numberer.RCM()) 268 | OData.AddObject(OpenSeesAPI.Analysis.System.BandGeneral()) 269 | OData.AddObject(OpenSeesAPI.Analysis.Test.EnergyIncr(1.e-6, 1000)) 270 | OData.AddObject(OpenSeesAPI.Analysis.Algorithm.KrylovNewton()) 271 | OData.AddObject(OpenSeesAPI.Analysis.Integrator.Static.LoadControl(1.0/NoOfGravitySteps,1,0.2,0.2)) 272 | OData.AddObject(OpenSeesAPI.Analysis.Analysis.Static()) 273 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok [analyze %d]'%NoOfGravitySteps)) 274 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('if {$ok == 0} {puts "Gravity Analysis Success" } else {puts "Gravity Analysis Failed"} ')) 275 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('loadConst -time 0.0')) 276 | 277 | ########################## Pushover Analysis ########################## 278 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Pushover Analysis')) 279 | 280 | ########################## Time History Analysis ########################## 281 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Time History Analysis')) 282 | 283 | #Analysis Options 284 | OData.AddObject(OpenSeesAPI.Analysis.Constraints.Plain()) 285 | OData.AddObject(OpenSeesAPI.Analysis.Numberer.RCM()) 286 | OData.AddObject(OpenSeesAPI.Analysis.System.BandGeneral()) 287 | OData.AddObject(OpenSeesAPI.Analysis.Test.NormDispIncr(1e-6, 1000)) 288 | OData.AddObject(OpenSeesAPI.Analysis.Algorithm.KrylovNewton()) 289 | OData.AddObject(OpenSeesAPI.Analysis.Integrator.Transient.Newmark(0.5,0.25)) 290 | OData.AddObject(OpenSeesAPI.Analysis.Analysis.Transient()) 291 | 292 | #Load Pattern 293 | OData.AddObject(OpenSeesAPI.Model.Pattern.UniformExcitation(400,1,TimeSeries)) 294 | 295 | #Run Analysis 296 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok 0;')) 297 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set Nsteps %d;'%len(GMData))) 298 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set step 0;')) 299 | 300 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('while {$ok == 0 & $step < [expr $Nsteps +1]} {')) 301 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok [analyze 1 %f]'%(Dt))) 302 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('puts "Running Time History Step: $step out of %d"'%len(GMData))) 303 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set step [expr $step+1]')) 304 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('}')) 305 | 306 | ########################## Close File ########################## 307 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Close File')) 308 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('wipe;')) 309 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('puts "Models Run Complete";')) 310 | 311 | ############################################################################## 312 | ### Start Running OpenSees File 313 | ############################################################################## 314 | 315 | ########################## Plot Geometry ########################## 316 | 317 | 318 | ########################## Run OpenSees Script ########################## 319 | OData.Executable.StartAnalysis(SuppressOutput=False) 320 | 321 | ########################## Plot Results ########################## 322 | Displ = np.loadtxt(ResultDirectory+'/'+Displacement_File_Name) 323 | Vel = np.loadtxt(ResultDirectory+'/'+Velocity_File_Name) 324 | Acc = np.loadtxt(ResultDirectory+'/'+Acceleration_File_Name) 325 | Reac = np.loadtxt(ResultDirectory+'/'+Reaction_File_Name) 326 | 327 | MaxD = max(abs(Displ[:,1])) 328 | MaxV = max(abs(Vel[:,1])) 329 | MaxA = max(abs(Acc[:,1])) 330 | 331 | try: 332 | os.remove(TCLFileDirectory+'/%s.out'%(ModelName)) 333 | except: 334 | pass 335 | 336 | # os.remove(TCLFileDirectory+'/%s.tcl'%(ModelName)) 337 | os.remove(ResultDirectory+'/'+Displacement_File_Name) 338 | os.remove(ResultDirectory+'/'+Velocity_File_Name) 339 | os.remove(ResultDirectory+'/'+Acceleration_File_Name) 340 | os.remove(ResultDirectory+'/'+Reaction_File_Name) 341 | 342 | DataPoints = len(GMData) 343 | 344 | g = 386.4 345 | t = Acc[0:DataPoints,0] 346 | ag = GMData[:]/g 347 | a = Acc[0:DataPoints,1] 348 | fs = -1*np.sum(Reac[0:DataPoints,1:],axis=1) 349 | u = Displ[0:DataPoints,1] 350 | 351 | import matplotlib.pylab as plt 352 | plt.figure(figsize=(12,12)) 353 | plt.subplot(2,2,1) 354 | plt.plot(t,ag,color='#000000') 355 | plt.xlabel('Time, s') 356 | plt.ylabel('$a_g$, g') 357 | 358 | plt.subplot(2,2,2) 359 | plt.plot(u,fs,color='#000000') 360 | plt.xlabel('$Roof Displacement$') 361 | plt.ylabel('$Base Shear$') 362 | 363 | plt.subplot(2,2,3) 364 | plt.plot(t,a,color='#000000') 365 | plt.xlabel('Time, t') 366 | plt.ylabel('$a$, g') 367 | 368 | plt.subplot(2,2,4) 369 | plt.plot(u,t,color='#000000') 370 | plt.xlabel('Roof Displacement') 371 | plt.ylabel('Time, t') 372 | 373 | plt.show() 374 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nassermarafi/OpenSeesAPI/697167cf4c73c4e094c9896d76cfca0eeeb97f09/test/__init__.py -------------------------------------------------------------------------------- /test/test.py: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | ##### This is a sample script that runs an SDOF analysis in OpenSees 3 | ##### using an Ibarra-Krawinkler Deterioation spring 4 | ##### Coded by Nasser Marafi (marafi@uw.edu) 5 | ##### Last Updated: 8/12/2015 6 | ##### Make sure to have a subfolder called /tcl/ with the OpenSees Executable File 7 | ############################################################################ 8 | __author__ = 'marafi' 9 | 10 | import numpy as np 11 | 12 | ########################## Input Parameters ########################## 13 | 14 | # This is Elcentro's Ground Motion in g 15 | GMData = 386.4*np.array([0.0063,0.00364,0.00099,0.00428,0.00758,0.01087,0.00682,0.00277,-0.00128,0.00368,0.00864,0.0136,0.00727,0.00094,0.0042,0.00221,0.00021,0.00444,0.00867,0.0129,0.01713,-0.00343,-0.024,-0.00992,0.00416,0.00528,0.01653,0.02779,0.03904,0.02449,0.00995,0.00961,0.00926,0.00892,-0.00486,-0.01864,-0.03242,-0.03365,-0.05723,-0.04534,-0.03346,-0.03201,-0.03056,-0.02911,-0.02766,-0.04116,-0.05466,-0.06816,-0.08166,-0.06846,-0.05527,-0.04208,-0.04259,-0.04311,-0.02428,-0.00545,0.01338,0.03221,0.05104,0.06987,0.0887,0.04524,0.00179,-0.04167,-0.08513,-0.12858,-0.17204,-0.12908,-0.08613,-0.08902,-0.09192,-0.09482,-0.09324,-0.09166,-0.09478,-0.09789,-0.12902,-0.07652,-0.02401,0.02849,0.08099,0.1335,0.186,0.2385,0.21993,0.20135,0.18277,0.1642,0.14562,0.16143,0.17725,0.13215,0.08705,0.04196,-0.00314,-0.04824,-0.09334,-0.13843,-0.18353,-0.22863,-0.27372,-0.31882,-0.25024,-0.18166,-0.11309,-0.04451,0.02407,0.09265,0.16123,0.22981,0.29839,0.23197,0.16554,0.09912,0.0327,-0.03372,-0.10014,-0.16656,-0.23299,-0.29941,-0.00421,0.29099,0.2238,0.15662,0.08943,0.02224,-0.04495,0.01834,0.08163,0.14491,0.2082,0.18973,0.17125,0.13759,0.10393,0.07027,0.03661,0.00295,-0.03071,-0.00561,0.01948,0.04458,0.06468,0.08478,0.10487,0.05895,0.01303,-0.03289,-0.07882,-0.03556,0.00771,0.05097,0.01013,-0.03071,-0.07156,-0.1124,-0.15324,-0.11314,-0.07304,-0.03294,0.00715,-0.0635,-0.13415,-0.2048,-0.12482,-0.04485,0.03513,0.1151,0.19508,0.12301,0.05094,-0.02113,-0.0932,-0.02663,0.03995,0.10653,0.17311,0.11283,0.05255,-0.00772,0.01064,0.029,0.04737,0.06573,0.02021,-0.0253,-0.07081,-0.04107,-0.01133,0.00288,0.01709,0.03131,-0.02278,-0.07686,-0.13095,-0.18504,-0.14347,-0.1019,-0.06034,-0.01877,0.0228,-0.00996,-0.04272,-0.02147,-0.00021,0.02104,-0.01459,-0.05022,-0.08585,-0.12148,-0.15711,-0.19274,-0.22837,-0.18145,-0.13453,-0.08761,-0.04069,0.00623,0.05316,0.10008,0.147,0.09754,0.04808,-0.00138,0.05141,0.1042,0.15699,0.20979,0.26258,0.16996,0.07734,-0.01527,-0.10789,-0.20051,-0.06786,0.06479,0.01671,-0.03137,-0.07945,-0.12753,-0.17561,-0.22369,-0.27177,-0.15851,-0.04525,0.06802,0.18128,0.14464,0.108,0.07137,0.03473,0.09666,0.1586,0.22053,0.18296,0.14538,0.1078,0.07023,0.03265,0.06649,0.10033,0.13417,0.10337,0.07257,0.04177,0.01097,-0.01983,0.04438,0.1086,0.17281,0.10416,0.03551,-0.03315,-0.1018,-0.07262,-0.04344,-0.01426,0.01492,-0.02025,-0.05543,-0.0906,-0.12578,-0.16095,-0.19613,-0.14784,-0.09955,-0.05127,-0.00298,-0.01952,-0.03605,-0.05259,-0.04182,-0.03106,-0.02903,-0.02699,0.02515,0.0177,0.02213,0.02656,0.00419,-0.01819,-0.04057,-0.06294,-0.02417,0.0146,0.05337,0.02428,-0.0048,-0.03389,-0.00557,0.02274,0.00679,-0.00915,-0.02509,-0.04103,-0.05698,-0.01826,0.02046,0.00454,-0.01138,-0.00215,0.00708,0.00496,0.00285,0.00074,-0.00534,-0.01141,0.00361,0.01863,0.03365,0.04867,0.0304,0.01213,-0.00614,-0.02441,0.01375,0.01099,0.00823,0.00547,0.00812,0.01077,-0.00692,-0.02461,-0.0423,-0.05999,-0.07768,-0.09538,-0.06209,-0.0288,0.00448,0.03777,0.01773,-0.00231,-0.02235,0.01791,0.05816,0.03738,0.0166,-0.00418,-0.02496,-0.04574,-0.02071,0.00432,0.02935,0.01526,0.01806,0.02086,0.00793,-0.00501,-0.01795,-0.03089,-0.01841,-0.00593,0.00655,-0.02519,-0.05693,-0.04045,-0.02398,-0.0075,0.00897,0.00384,-0.00129,-0.00642,-0.01156,-0.02619,-0.04082,-0.05545,-0.04366,-0.03188,-0.06964,-0.05634,-0.04303,-0.02972,-0.01642,-0.00311,0.0102,0.0235,0.03681,0.05011,0.02436,-0.00139,-0.02714,-0.00309,0.02096,0.04501,0.06906,0.05773,0.0464,0.03507,0.03357,0.03207,0.03057,0.0325,0.03444,0.03637,0.01348,-0.00942,-0.03231,-0.02997,-0.03095,-0.03192,-0.02588,-0.01984,-0.01379,-0.00775,-0.01449,-0.02123,0.01523,0.0517,0.08816,0.12463,0.16109,0.12987,0.09864,0.06741,0.03618,0.00495,0.0042,0.00345,0.00269,-0.05922,-0.12112,-0.18303,-0.12043,-0.05782,0.00479,0.0674,0.13001,0.08373,0.03745,0.06979,0.10213,-0.03517,-0.17247,-0.13763,-0.10278,-0.06794,-0.0331,-0.03647,-0.03984,-0.00517,0.0295,0.06417,0.09883,0.1335,0.05924,-0.01503,-0.08929,-0.16355,-0.06096,0.04164,0.01551,-0.01061,-0.03674,-0.06287,-0.08899,-0.0543,-0.01961,0.01508,0.04977,0.08446,0.05023,0.016,-0.01823,-0.05246,-0.08669,-0.06769,-0.0487,-0.0297,-0.01071,0.00829,-0.00314,0.02966,0.06246,-0.00234,-0.06714,-0.04051,-0.01388,0.01274,0.00805,0.03024,0.05243,0.02351,-0.00541,-0.03432,-0.06324,-0.09215,-0.12107,-0.0845,-0.04794,-0.01137,0.0252,0.06177,0.04028,0.0188,0.04456,0.07032,0.09608,0.12184,0.0635,0.00517,-0.05317,-0.03124,-0.0093,0.01263,0.03457,0.03283,0.03109,0.02935,0.04511,0.06087,0.07663,0.09239,0.05742,0.02245,-0.01252,0.0068,0.02611,0.04543,0.01571,-0.01402,-0.04374,-0.07347,-0.0399,-0.00633,0.02724,0.0608,0.03669,0.01258,-0.01153,-0.03564,-0.00677,0.0221,0.05098,0.07985,0.06915,0.05845,0.04775,0.03706,0.02636,0.05822,0.09009,0.12196,0.10069,0.07943,0.05816,0.03689,0.01563,-0.00564,-0.0269,-0.04817,-0.06944,-0.0907,-0.11197,-0.11521,-0.11846,-0.1217,-0.12494,-0.165,-0.20505,-0.15713,-0.10921,-0.06129,-0.01337,0.03455,0.08247,0.07576,0.06906,0.06236,0.08735,0.11235,0.13734,0.12175,0.10616,0.09057,0.07498,0.08011,0.08524,0.09037,0.06208,0.03378,0.00549,-0.02281,-0.05444,-0.0403,-0.02615,-0.01201,-0.02028,-0.02855,-0.06243,-0.03524,-0.00805,-0.04948,-0.03643,-0.02337,-0.03368,-0.01879,-0.00389,0.011,0.02589,0.01446,0.00303,-0.0084,0.00463,0.01766,0.03069,0.04372,0.02165,-0.00042,-0.02249,-0.04456,-0.03638,-0.02819,-0.02001,-0.01182,-0.02445,-0.03707,-0.04969,-0.05882,-0.06795,-0.07707,-0.0862,-0.09533,-0.06276,-0.03018,0.00239,0.03496,0.04399,0.05301,0.03176,0.01051,-0.01073,-0.03198,-0.05323,0.00186,0.05696,0.01985,-0.01726,-0.05438,-0.01204,0.03031,0.07265,0.11499,0.07237,0.02975,-0.01288,0.01212,0.03711,0.03517,0.03323,0.01853,0.00383,0.00342,-0.02181,-0.04704,-0.07227,-0.0975,-0.12273,-0.08317,-0.04362,-0.00407,0.03549,0.07504,0.1146,0.07769,0.04078,0.00387,0.00284,0.00182,-0.05513,0.04732,0.05223,0.05715,0.06206,0.06698,0.07189,0.02705,-0.01779,-0.06263,-0.10747,-0.15232,-0.12591,-0.0995,-0.07309,-0.04668,-0.02027,0.00614,0.03255,0.00859,-0.01537,-0.03932,-0.06328,-0.03322,-0.00315,0.02691,0.01196,-0.003,0.00335,0.0097,0.01605,0.02239,0.04215,0.06191,0.08167,0.03477,-0.01212,-0.01309,-0.01407,-0.05274,-0.02544,0.00186,0.02916,0.05646,0.08376,0.01754,-0.04869,-0.02074,0.00722,0.03517,-0.00528,-0.04572,-0.08617,-0.0696,-0.05303,-0.03646,-0.01989,-0.00332,0.01325,0.02982,0.01101,-0.00781,-0.02662,-0.00563,0.01536,0.03635,0.05734,0.03159,0.00584,-0.01992,-0.00201,0.01589,-0.01024,-0.03636,-0.06249,-0.0478,-0.03311,-0.04941,-0.0657,-0.082,-0.0498,-0.0176,0.0146,0.0468,0.079,0.0475,0.016,-0.0155,-0.00102,0.01347,0.02795,0.04244,0.05692,0.03781,0.0187,-0.00041,-0.01952,-0.00427,0.01098,0.02623,0.04148,0.01821,-0.00506,-0.00874,-0.03726,-0.06579,-0.026,0.0138,0.05359,0.09338,0.05883,0.02429,-0.01026,-0.0448,-0.01083,-0.01869,-0.02655,-0.03441,-0.02503,-0.01564,-0.00626,-0.01009,-0.01392,0.0149,0.04372,0.03463,0.02098,0.00733,-0.00632,-0.01997,0.00767,0.03532,0.03409,0.03287,0.03164,0.02403,0.01642,0.00982,0.00322,-0.00339,0.02202,-0.01941,-0.06085,-0.10228,-0.07847,-0.05466,-0.03084,-0.00703,0.01678,0.01946,0.02214,0.02483,0.01809,-0.00202,-0.02213,-0.00278,0.01656,0.0359,0.05525,0.07459,0.06203,0.04948,0.03692,-0.00145,0.04599,0.04079,0.03558,0.03037,0.03626,0.04215,0.04803,0.05392,0.04947,0.04502,0.04056,0.03611,0.03166,0.00614,-0.01937,-0.04489,-0.0704,-0.09592,-0.07745,-0.05899,-0.04052,-0.02206,-0.00359,0.01487,0.01005,0.00523,0.00041,-0.00441,-0.00923,-0.01189,-0.01523,-0.01856,-0.0219,-0.00983,0.00224,0.01431,0.00335,-0.0076,-0.01856,-0.00737,0.00383,0.01502,0.02622,0.01016,-0.0059,-0.02196,-0.00121,0.01953,0.04027,0.02826,0.01625,0.00424,0.00196,-0.00031,-0.00258,-0.00486,-0.00713,-0.00941,-0.01168,-0.01396,-0.0175,-0.02104,-0.02458,-0.02813,-0.03167,-0.03521,-0.04205,-0.04889,-0.03559,-0.02229,-0.00899,0.00431,0.01762,0.00714,-0.00334,-0.01383,0.01314,0.04011,0.06708,0.0482,0.02932,0.01043,-0.00845,-0.02733,-0.04621,-0.03155,-0.01688,-0.00222,0.01244,0.02683,0.04121,0.05559,0.03253,0.00946,-0.0136,-0.01432,-0.01504,-0.01576,-0.04209,-0.02685,-0.01161,0.00363,0.01887,0.03411,0.03115,0.02819,0.02917,0.03015,0.03113,0.00388,-0.02337,-0.05062,-0.0382,-0.02579,-0.01337,-0.00095,0.01146,0.02388,0.03629,0.01047,-0.01535,-0.04117,-0.06699,-0.05207,-0.03715,-0.02222,-0.0073,0.00762,0.02254,0.03747,0.04001,0.04256,0.04507,0.04759,0.0501,0.04545,0.0408,0.02876,0.01671,0.00467,-0.00738,-0.00116,0.00506,0.01128,0.0175,-0.00211,-0.02173,-0.04135,-0.06096,-0.08058,-0.06995,-0.05931,-0.04868,-0.03805,-0.02557,-0.0131,-0.00063,0.01185,0.02432,0.0368,0.04927,0.02974,0.01021,-0.00932,-0.02884,-0.04837,-0.0679,-0.04862,-0.02934,-0.01006,0.00922,0.02851,0.04779,0.02456,0.00133,-0.0219,-0.04513,-0.06836,-0.04978,-0.0312,-0.01262,0.00596,0.02453,0.04311,0.06169,0.08027,0.09885,0.06452,0.03019,-0.00414,-0.03848,-0.07281,-0.05999,-0.04717,-0.03435,-0.03231,-0.03028,-0.02824,-0.00396,0.02032,0.00313,-0.01406,-0.03124,-0.04843,-0.06562,-0.05132,-0.03702,-0.02272,-0.00843,0.00587,0.02017,0.02698,0.03379,0.04061,0.04742,0.05423,0.03535,0.01647,0.01622,0.01598,0.01574,0.00747,-0.0008,-0.00907,0.00072,0.01051,0.0203,0.03009,0.03989,0.03478,0.02967,0.02457,0.03075,0.03694,0.04313,0.04931,0.0555,0.06168,-0.00526,-0.0722,-0.06336,-0.05451,-0.04566,-0.03681,-0.03678,-0.03675,-0.03672,-0.01765,0.00143,0.02051,0.03958,0.05866,0.03556,0.01245,-0.01066,-0.03376,-0.05687,-0.04502,-0.03317,-0.02131,-0.00946,0.00239,-0.00208,-0.00654,-0.01101,-0.01548,-0.012,-0.00851,-0.00503,-0.00154,0.00195,0.00051,-0.00092,0.01135,0.02363,0.0359,0.04818,0.06045,0.07273,0.02847,-0.01579,-0.06004,-0.05069,-0.04134,-0.03199,-0.03135,-0.03071,-0.03007,-0.01863,-0.00719,0.00425,0.0157,0.02714,0.03858,0.02975,0.02092,0.02334,0.02576,0.02819,0.03061,0.03304,0.01371,-0.00561,-0.02494,-0.02208,-0.01923,-0.01638,-0.01353,-0.01261,-0.0117,-0.00169,0.00833,0.01834,0.02835,0.03836,0.04838,0.03749,0.0266,0.01571,0.00482,-0.00607,-0.01696,-0.0078,0.00136,0.01052,0.01968,0.02884,-0.00504,-0.03893,-0.02342,-0.00791,0.00759,0.0231,0.00707,-0.00895,-0.02498,-0.041,-0.05703,-0.0292,-0.00137,0.02645,0.05428,0.03587,0.01746,-0.00096,-0.01937,-0.03778,-0.02281,-0.00784,0.00713,0.0221,0.03707,0.05204,0.06701,0.08198,0.03085,-0.02027,-0.0714,-0.12253,-0.08644,-0.05035,-0.01426,0.02183,0.05792,0.094,0.13009,0.03611,-0.05787,-0.04802,-0.03817,-0.02832,-0.01846,-0.00861,-0.03652,-0.06444,-0.06169,-0.05894,-0.05618,-0.06073,-0.06528,-0.04628,-0.02728,-0.00829,0.01071,0.0297,0.03138,0.03306,0.03474,0.03642,0.04574,0.05506,0.06439,0.07371,0.08303,0.03605,-0.01092,-0.0579,-0.04696,-0.03602,-0.02508,-0.01414,-0.03561,-0.05708,-0.07855,-0.06304,-0.04753,-0.03203,-0.01652,-0.00102,0.00922,0.01946,0.0297,0.03993,0.05017,0.06041,0.07065,0.08089,-0.00192,-0.08473,-0.07032,-0.0559,-0.04148,-0.05296,-0.06443,-0.0759,-0.08738,-0.09885,-0.06798,-0.0371,-0.00623,0.02465,0.05553,0.0864,0.11728,0.14815,0.08715,0.02615,-0.03485,-0.09584,-0.071,-0.04616,-0.02132,0.00353,0.02837,0.05321,-0.00469,-0.06258,-0.12048,-0.0996,-0.07872,-0.05784,-0.03696,-0.01608,0.0048,0.02568,0.04656,0.06744,0.08832,0.1092,0.13008,0.10995,0.08982,0.06969,0.04955,0.04006,0.03056,0.02107,0.01158,0.0078,0.00402,0.00024,-0.00354,-0.00732,-0.0111,-0.0078,-0.0045,-0.0012,0.0021,0.0054,-0.00831,-0.02203,-0.03575,-0.04947,-0.06319,-0.05046,-0.03773,-0.025,-0.01227,0.00046,0.00482,0.00919,0.01355,0.01791,0.02228,0.00883,-0.00462,-0.01807,-0.03152,-0.02276,-0.01401,-0.00526,0.0035,0.01225,0.02101,0.01437,0.00773,0.0011,0.00823,0.01537,0.02251,0.01713,0.01175,0.00637,0.01376,0.02114,0.02852,0.03591,0.04329,0.03458,0.02587,0.01715,0.00844,-0.00027,-0.00898,-0.00126,0.00645,0.01417,0.02039,0.02661,0.03283,0.03905,0.04527,0.03639,0.0275,0.01862,0.00974,0.00086,-0.01333,-0.02752,-0.04171,-0.02812,-0.01453,-0.00094,0.01264,0.02623,0.0169,0.00756,-0.00177,-0.01111,-0.02044,-0.02977,-0.03911,-0.02442,-0.00973,0.00496,0.01965,0.03434,0.02054,0.00674,-0.00706,-0.02086,-0.03466,-0.02663,-0.0186,-0.01057,-0.00254,-0.00063,0.00128,0.00319,0.0051,0.00999,0.01488,0.00791,0.00093,-0.00605,0.00342,0.01288,0.02235,0.03181,0.04128,0.02707,0.01287,-0.00134,-0.01554,-0.02975,-0.04395,-0.03612,-0.02828,-0.02044,-0.0126,-0.00476,0.00307,0.01091,0.00984,0.00876,0.00768,0.00661,0.01234,0.01807,0.0238,0.02953,0.03526,0.02784,0.02042,0.013,-0.03415,-0.00628,-0.00621,-0.00615,-0.00609,-0.00602,-0.00596,-0.0059,-0.00583,-0.00577,-0.00571,-0.00564,-0.00558,-0.00552,-0.00545,-0.00539,-0.00532,-0.00526,-0.0052,-0.00513,-0.00507,-0.00501,-0.00494,-0.00488,-0.00482,-0.00475,-0.00469,-0.00463,-0.00456,-0.0045,-0.00444,-0.00437,-0.00431,-0.00425,-0.00418,-0.00412,-0.00406,-0.00399,-0.00393,-0.00387,-0.0038,-0.00374,-0.00368,-0.00361,-0.00355,-0.00349,-0.00342,-0.00336,-0.0033,-0.00323,-0.00317,-0.00311,-0.00304,-0.00298,-0.00292,-0.00285,-0.00279,-0.00273,-0.00266,-0.0026,-0.00254,-0.00247,-0.00241,-0.00235,-0.00228,-0.00222,-0.00216,-0.00209,-0.00203,-0.00197,-0.0019,-0.00184,-0.00178,-0.00171,-0.00165,-0.00158,-0.00152,-0.00146,-0.00139,-0.00133,-0.00127,-0.0012,-0.00114,-0.00108,-0.00101,-0.00095,-0.00089,-0.00082,-0.00076,-0.0007,-0.00063,-0.00057,-0.00051,-0.00044,-0.00038,-0.00032,-0.00025,-0.00019,-0.00013,-0.00006,0]+list(np.zeros(1000))) 16 | Dt = 0.02 17 | T = 1.0 18 | Dy = 2 19 | Zeta = 0.05 20 | PY = 0.05 21 | PC = 0.1 22 | LamdaSCA = 100 23 | LamdaK = 50 24 | cRate = 1 25 | Mu = 8 26 | Kappa = 0.01 27 | 28 | # OpenSeesCommand = os.getcwd()+'//tcl//OpenSees' # Path to the OpenSees Executable File 29 | OpenSeesCommand = 'OpenSees' 30 | 31 | ########################## Pre-Initialization ########################## 32 | import OpenSeesAPI 33 | import os 34 | import numpy as np 35 | 36 | g=386.1 37 | #Mass 38 | m = 1 39 | wn = 2*np.pi/T 40 | 41 | #Stiffness 42 | k = wn**2.0*m 43 | 44 | #Damping 2% 45 | c=Zeta*2*m*wn 46 | 47 | ########################## Initializing ########################## 48 | 49 | ### Create OpenSees Database 50 | 51 | import time 52 | import uuid 53 | randomnumber = str(uuid.uuid4()).upper() 54 | timestamp = time.strftime("%y%m%d-%H%M%S")+randomnumber 55 | ModelName = 'ExampleScript' 56 | FileName = '%s-%s.tcl'%(ModelName,timestamp) 57 | TCLFileDirectory = os.getcwd()+'/tcl/' 58 | ResultDirectory = os.getcwd()+'/tcl/Results/' 59 | 60 | if not os.path.exists(TCLFileDirectory): #Make Directory is unavailable 61 | os.makedirs(TCLFileDirectory) 62 | if not os.path.exists(ResultDirectory): #Make Directory is unavailable 63 | os.makedirs(ResultDirectory) 64 | 65 | OData = OpenSeesAPI.Database.Collector(OpenSeesCommand, TCLFileDirectory, FileName) 66 | 67 | ########################## Setup and Source Definition ########################## 68 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Initialization')) 69 | OData.AddObject(OpenSeesAPI.BasicBuilder(2,3)) 70 | 71 | ########################## Define Building Geometry, Nodes and Constraints ########################## 72 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Geometry Setup')) 73 | 74 | SupportNode = OData.CreateNode(0,0) 75 | MassNode = OData.CreateNode(0,0) 76 | OData.AddConstraint(OpenSeesAPI.Node.Mass(MassNode,[m,1e-6,1e-6])) 77 | 78 | ########################## Define Geometric Transformations ########################## 79 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Geometric Transformations')) 80 | 81 | #Define Geometry Transformations for Beams and Column 82 | GeoTransfLinear = OpenSeesAPI.GeomTransf.Linear(1) 83 | OData.AddObject(GeoTransfLinear) 84 | 85 | ############################################################################## 86 | ### All OpenSEES Objects are adding directly to the Database Beyond This Point 87 | ############################################################################## 88 | 89 | ########################## Define Materials and Sections ########################## 90 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Materials and Sections')) 91 | 92 | ########################## Define Rotational Springs for Plastic Hinge ########################## 93 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Rotational Springs for Plastic Hinge')) 94 | 95 | #Define Rotational Spring 96 | #### Collector Should Give ID 97 | 98 | ThetaP = Dy*Mu - Dy 99 | Ult = k*Dy + k*PY*ThetaP 100 | ThetaPC = Ult/(k*PC) 101 | Spring = OpenSeesAPI.Material.UniaxialMaterial.ModIMKPinched(1,k,PY,PY,k*Dy,-1*k*Dy, 0.1, 0.1, 0.5, LamdaSCA,LamdaSCA,LamdaSCA,LamdaK,cRate,cRate,cRate,cRate,ThetaP, ThetaP, ThetaPC, ThetaPC, Kappa, Kappa, (ThetaPC+ThetaP+Dy)*2, (ThetaPC+ThetaP+Dy)*2, 1.0, 1.0) 102 | OData.AddMaterial(Spring) 103 | 104 | ########################## Define Elements ########################## 105 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Define Elements')) 106 | OData.AddElement(OpenSeesAPI.Element.ZeroLength(OData.GetFreeElementId(9,1),SupportNode, MassNode, [Spring],[1])) 107 | 108 | ########################## Define Constraints ########################## 109 | OData.AddConstraint(OpenSeesAPI.Constraint.Fix(SupportNode,[1,1,1])) 110 | OData.AddConstraint(OpenSeesAPI.Constraint.Fix(MassNode,[0,1,1])) 111 | 112 | ############################################################################## 113 | ### Start Writing Elements to the Executible File 114 | ############################################################################## 115 | 116 | ########################## Writing Model to TCL File ########################## 117 | OData.WriteModel() 118 | 119 | ########################## Eigenvalue Analysis ########################## 120 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Eigenvalue Analysis')) 121 | OData.AddObject(OpenSeesAPI.Analysis.Eigen(1, fullGenLapack=True)) 122 | 123 | ########################## Rayleigh Damping ########################## 124 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Rayleigh Damping')) 125 | # Adding Rayleigh Damping to the Mass Matrix Only 126 | OData.AddObject(OpenSeesAPI.Model.Node.Rayleigh(2 * Zeta * 2 * np.pi / T, 0, 0, 0)) 127 | 128 | ########################## Loads ########################## 129 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Loads')) 130 | 131 | ########################## Time Series ########################## 132 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Time Series')) 133 | 134 | TimeSeries = OpenSeesAPI.TimeSeries.Path(1,Dt, GMData) 135 | OData.AddObject(TimeSeries) 136 | 137 | ########################## Recorders ########################## 138 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Recorder Setup')) 139 | 140 | OutputFolder = 'Results' 141 | 142 | Displacement_File_Name = '%s-NodeD-%s.dat'%(ModelName,timestamp) 143 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Displacement_File_Name, [MassNode], [1], 'disp')) 144 | 145 | Velocity_File_Name = '%s-NodeV-%s.dat'%(ModelName,timestamp) 146 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Velocity_File_Name, [MassNode], [1], 'vel')) 147 | 148 | Acceleration_File_Name = '%s-NodeA-%s.dat'%(ModelName,timestamp) 149 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Acceleration_File_Name, [MassNode], [1], 'accel','-timeSeries %d'%TimeSeries.id)) 150 | 151 | Reaction_File_Name = '%s-NodeReact-%s.dat'%(ModelName,timestamp) 152 | OData.AddObject(OpenSeesAPI.Output.Recorder.Node(OutputFolder+'/'+Reaction_File_Name, [SupportNode], [1], 'reaction')) 153 | 154 | ########################## Display Results ########################## 155 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Display Results')) 156 | 157 | ########################## Gravity Analysis ########################## 158 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Gravity Analysis')) 159 | 160 | ########################## Pushover Analysis ########################## 161 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Pushover Analysis')) 162 | 163 | ########################## Time History Analysis ########################## 164 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Time History Analysis')) 165 | 166 | #Analysis Options 167 | OData.AddObject(OpenSeesAPI.Analysis.Constraints.Transformation()) 168 | OData.AddObject(OpenSeesAPI.Analysis.Numberer.RCM()) 169 | OData.AddObject(OpenSeesAPI.Analysis.System.BandGeneral()) 170 | OData.AddObject(OpenSeesAPI.Analysis.Test.EnergyIncr(1e-6, 10)) 171 | OData.AddObject(OpenSeesAPI.Analysis.Algorithm.KrylovNewton()) 172 | OData.AddObject(OpenSeesAPI.Analysis.Integrator.Transient.Newmark(0.5,0.25)) 173 | OData.AddObject(OpenSeesAPI.Analysis.Analysis.Transient()) 174 | 175 | #Load Pattern 176 | OData.AddObject(OpenSeesAPI.Pattern.UniformExcitation(400,1,TimeSeries)) 177 | 178 | #Run Analysis 179 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok 0;')) 180 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set Nsteps %d;'%len(GMData))) 181 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set step 0;')) 182 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('while {$ok == 0 & $step < [expr $Nsteps +1]} {')) 183 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set ok [analyze 1 %f]'%Dt)) 184 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('puts "Running Time History Step: $step out of %d"'%len(GMData))) 185 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('set step [expr $step+1]')) 186 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('}')) 187 | 188 | ########################## Close File ########################## 189 | OData.AddObject(OpenSeesAPI.TCL.CodeTitle('Close File')) 190 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('wipe;')) 191 | OData.AddObject(OpenSeesAPI.TCL.TCLScript('puts "Models Run Complete";')) 192 | 193 | ############################################################################## 194 | ### Start Running OpenSees File 195 | ############################################################################## 196 | 197 | ########################## Plot Geometry ########################## 198 | 199 | 200 | ########################## Run OpenSees Script ########################## 201 | --------------------------------------------------------------------------------