Exemple #1
0
def modal_response(numEigen):

    # calculate eigenvalues
    eigenValues = op.eigen(
        '-genBandArpack',
        numEigen)  #can be either of: {'-genBandArpack', '-fullGenLapack'}
    return eigenValues
Exemple #2
0
    def eigen(self, struct, mode_count=1):
        """
        Perform a modal analysis and get the vibration periods of the structure. 
        
        Parameters
        ----------
        struct: Structure
            The structure or system to analyze.
        mode_count: int, optional
            The number of vibration modes to evaluate. Default: 1.

        Returns
        -------
        T_list: Series
            A list of vibration periods corresponding to the requested number of
            vibration modes. 

        """
        # initialize the analysis
        self._initialize()

        # define the structure - remove damping
        struct = deepcopy(struct)
        struct.xi = 0.
        struct.create_FEM()

        eigens = ops.eigen('-fullGenLapack', mode_count)
        T_list = 2 * np.pi / np.sqrt(np.array(eigens))

        return pd.Series(T_list, index=np.arange(1, mode_count + 1))
Exemple #3
0
def test_ElasticFrame():
    #
    # some parameter
    #
    PI = 2.0 * asin(1.0)
    g = 386.4
    ft = 12.0
    Load1 = 1185.0
    Load2 = 1185.0
    Load3 = 970.0

    # floor masses
    m1 = Load1 / (4 * g)  # 4 nodes per floor
    m2 = Load2 / (4 * g)
    m3 = Load3 / (4 * g)

    # floor distributed loads
    w1 = Load1 / (90 * ft)  # frame 90 ft long
    w2 = Load2 / (90 * ft)
    w3 = Load3 / (90 * ft)

    # ------------------------------
    # Start of model generation
    # ------------------------------

    # Remove existing model
    ops.wipe()

    # Create ModelBuilder (with two-dimensions and 2 DOF/node)
    ops.model('BasicBuilder', '-ndm', 2, '-ndf', 3)

    # Create nodes
    # ------------

    # Create nodes & add to Domain - command: node nodeId xCrd yCrd <-mass massX massY massRz>
    # NOTE: mass in optional
    ops.node(1, 0.0, 0.0)
    ops.node(2, 360.0, 0.0)
    ops.node(3, 720.0, 0.0)
    ops.node(4, 1080.0, 0.0)
    ops.node(5, 0.0, 162.0, '-mass', m1, m1, 0.0)
    ops.node(6, 360.0, 162.0, '-mass', m1, m1, 0.0)
    ops.node(7, 720.0, 162.0, '-mass', m1, m1, 0.0)
    ops.node(8, 1080.0, 162.0, '-mass', m1, m1, 0.0)
    ops.node(9, 0.0, 324.0, '-mass', m2, m2, 0.0)
    ops.node(10, 360.0, 324.0, '-mass', m2, m2, 0.0)
    ops.node(11, 720.0, 324.0, '-mass', m2, m2, 0.0)
    ops.node(12, 1080.0, 324.0, '-mass', m2, m2, 0.0)
    ops.node(13, 0.0, 486.0, '-mass', m3, m3, 0.0)
    ops.node(14, 360.0, 486.0, '-mass', m3, m3, 0.0)
    ops.node(15, 720.0, 486.0, '-mass', m3, m3, 0.0)
    ops.node(16, 1080.0, 486.0, '-mass', m3, m3, 0.0)

    # the boundary conditions - command: fix nodeID xResrnt? yRestrnt? rZRestrnt?
    ops.fix(1, 1, 1, 1)
    ops.fix(2, 1, 1, 1)
    ops.fix(3, 1, 1, 1)
    ops.fix(4, 1, 1, 1)

    # Define geometric transformations for beam-column elements
    ops.geomTransf('Linear', 1)  # beams
    ops.geomTransf('PDelta', 2)  # columns

    # Define elements
    # Create elastic beam-column - command: element elasticBeamColumn eleID node1 node2 A E Iz geomTransfTag

    # Define the Columns
    ops.element('elasticBeamColumn', 1, 1, 5, 75.6, 29000.0, 3400.0,
                2)  # W14X257
    ops.element('elasticBeamColumn', 2, 5, 9, 75.6, 29000.0, 3400.0,
                2)  # W14X257
    ops.element('elasticBeamColumn', 3, 9, 13, 75.6, 29000.0, 3400.0,
                2)  # W14X257
    ops.element('elasticBeamColumn', 4, 2, 6, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 5, 6, 10, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 6, 10, 14, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 7, 3, 7, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 8, 7, 11, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 9, 11, 15, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 10, 4, 8, 75.6, 29000.0, 3400.0,
                2)  # W14X257
    ops.element('elasticBeamColumn', 11, 8, 12, 75.6, 29000.0, 3400.0,
                2)  # W14X257
    ops.element('elasticBeamColumn', 12, 12, 16, 75.6, 29000.0, 3400.0,
                2)  # W14X257

    # Define the Beams
    ops.element('elasticBeamColumn', 13, 5, 6, 34.7, 29000.0, 5900.0,
                1)  # W33X118
    ops.element('elasticBeamColumn', 14, 6, 7, 34.7, 29000.0, 5900.0,
                1)  # W33X118
    ops.element('elasticBeamColumn', 15, 7, 8, 34.7, 29000.0, 5900.0,
                1)  # W33X118
    ops.element('elasticBeamColumn', 16, 9, 10, 34.2, 29000.0, 4930.0,
                1)  # W30X116
    ops.element('elasticBeamColumn', 17, 10, 11, 34.2, 29000.0, 4930.0,
                1)  # W30X116
    ops.element('elasticBeamColumn', 18, 11, 12, 34.2, 29000.0, 4930.0,
                1)  # W30X116
    ops.element('elasticBeamColumn', 19, 13, 14, 20.1, 29000.0, 1830.0,
                1)  # W24X68
    ops.element('elasticBeamColumn', 20, 14, 15, 20.1, 29000.0, 1830.0,
                1)  # W24X68
    ops.element('elasticBeamColumn', 21, 15, 16, 20.1, 29000.0, 1830.0,
                1)  # W24X68

    # Define loads for Gravity Analysis
    # ---------------------------------

    #create a Linear TimeSeries (load factor varies linearly with time): command timeSeries Linear tag
    ops.timeSeries('Linear', 1)

    # Create a Plain load pattern with a linear TimeSeries:
    #  command pattern Plain tag timeSeriesTag { loads }
    ops.pattern('Plain', 1, 1)
    ops.eleLoad('-ele', 13, 14, 15, '-type', '-beamUniform', -w1)
    ops.eleLoad('-ele', 16, 17, 18, '-type', '-beamUniform', -w2)
    ops.eleLoad('-ele', 19, 20, 21, '-type', '-beamUniform', -w3)

    # ---------------------------------
    # Create Analysis for Gravity Loads
    # ---------------------------------

    # Create the system of equation, a SPD using a band storage scheme
    ops.system('BandSPD')

    # Create the DOF numberer, the reverse Cuthill-McKee algorithm
    ops.numberer('RCM')

    # Create the constraint handler, a Plain handler is used as h**o constraints
    ops.constraints('Plain')

    # Create the integration scheme, the LoadControl scheme using steps of 1.0
    ops.integrator('LoadControl', 1.0)

    # Create the solution algorithm, a Linear algorithm is created
    ops.test('NormDispIncr', 1.0e-10, 6)
    ops.algorithm('Newton')

    # create the analysis object
    ops.analysis('Static')

    # ---------------------------------
    # Perform Gravity Analysis
    # ---------------------------------

    ops.analyze(1)
    # print "node 5: nodeDisp 5"
    # print "node 6: nodeDisp 6"
    # print "node 7: nodeDisp 7"
    # print "node 8: nodeDisp 8"
    # print "node 9: nodeDisp 9"
    # print "node 10: nodeDisp 10"
    # ---------------------------------
    # Check Equilibrium
    # ---------------------------------

    # invoke command to determine nodal reactions
    ops.reactions()

    node1Rxn = ops.nodeReaction(
        1
    )  # nodeReaction command returns nodal reactions for specified node in a list
    node2Rxn = ops.nodeReaction(2)
    node3Rxn = ops.nodeReaction(3)
    node4Rxn = ops.nodeReaction(4)

    inputedFy = -Load1 - Load2 - Load3  # loads added negative Fy diren to ele
    computedFx = node1Rxn[0] + node2Rxn[0] + node3Rxn[0] + node4Rxn[0]
    computedFy = node1Rxn[1] + node2Rxn[1] + node3Rxn[1] + node4Rxn[1]

    print("\nEqilibrium Check After Gravity:")
    print("SumX: Inputed: 0.0 + Computed:", computedFx, " =  ",
          0.0 + computedFx)
    print("SumY: Inputed: ", inputedFy, " + Computed: ", computedFy, " =  ",
          inputedFy + computedFy)

    # ---------------------------------
    # Lateral Load
    # ---------------------------------

    # gravity loads constant and time in domain to e 0.0
    ops.loadConst('-time', 0.0)

    ops.timeSeries('Linear', 2)
    ops.pattern('Plain', 2, 2)
    ops.load(13, 220.0, 0.0, 0.0)
    ops.load(9, 180.0, 0.0, 0.0)
    ops.load(5, 90.0, 0.0, 0.0)

    # ---------------------------------
    # Create Recorder
    # ---------------------------------

    #recorder Element -file EleForces.out -ele 1 4 7 10 forces

    # ---------------------------------
    # Perform Lateral Analysis
    # ---------------------------------

    ops.analyze(1)
    # print "node 5: nodeDisp 5"
    # print "node 6: nodeDisp 6"
    # print "node 7: nodeDisp 7"
    # print "node 8: nodeDisp 8"
    # print "node 9: nodeDisp 9"
    # print "node 10: nodeDisp 10"
    # ---------------------------------
    # Check Equilibrium
    # ---------------------------------

    ops.reactions()

    node1Rxn = ops.nodeReaction(
        1
    )  # =nodeReaction( command returns nodal reactions for specified node in a list
    node2Rxn = ops.nodeReaction(2)
    node3Rxn = ops.nodeReaction(3)
    node4Rxn = ops.nodeReaction(4)

    inputedFx = 220.0 + 180.0 + 90.0
    computedFx = node1Rxn[0] + node2Rxn[0] + node3Rxn[0] + node4Rxn[0]
    computedFy = node1Rxn[1] + node2Rxn[1] + node3Rxn[1] + node4Rxn[1]

    print("\nEqilibrium Check After Lateral Loads:")
    print("SumX: Inputed: ", inputedFx, " + Computed: ", computedFx, " =  ",
          inputedFx + computedFx)
    print("SumY: Inputed: ", inputedFy, " + Computed: ", computedFy, " =  ",
          inputedFy + computedFy)

    # print ele information for columns at base
    #print ele 1 4 7 10

    # ---------------------------------
    # Check Eigenvalues
    # ---------------------------------

    eigenValues = ops.eigen(5)

    print("\nEigenvalues:")
    eigenValue = eigenValues[0]
    T1 = 2 * PI / sqrt(eigenValue)
    print("T1 = ", T1)

    eigenValue = eigenValues[1]
    T2 = 2 * PI / sqrt(eigenValue)
    print("T2 = ", T2)

    eigenValue = eigenValues[2]
    T3 = 2 * PI / sqrt(eigenValue)
    print("T3 = ", T3)

    eigenValue = eigenValues[3]
    T4 = 2 * PI / sqrt(eigenValue)
    print("T4 = ", T4)

    eigenValue = eigenValues[4]
    T5 = 2 * PI / sqrt(eigenValue)
    print("T5 = ", T5)

    assert abs(T1 - 1.0401120938612862) < 1e-12 and abs(
        T2 - 0.3526488583606463
    ) < 1e-12 and abs(T3 - 0.1930409642350476) < 1e-12 and abs(
        T4 - 0.15628823050715784) < 1e-12 and abs(T5 -
                                                  0.13080166151268388) < 1e-12

    #recorder Node -file eigenvector.out -nodeRange 5 16 -dof 1 2 3 eigen 0
    #record

    print("==========================")
Exemple #4
0
# --------------------------------------------------------------------------------------------------
#	OpenSees (Tcl) code by:	Silvia Mazzoni & Frank McKenna, 2006
##########################################################################################################################################################################
import openseespy.opensees as op
#import the os module
#import os
import math
op.wipe()
#########################################################################################################################################################################
import InelasticFiberSection
#applying Dynamic Ground motion analysis
Tol = 1e-8
GMdirection = 1
GMfile = 'BM68elc.acc'
GMfact = 1.0
Lambda = op.eigen('-fullGenLapack', 1)  # eigenvalue mode 1
Omega = math.pow(Lambda, 0.5)
betaKcomm = 2 * (0.02 / Omega)

xDamp = 0.02  # 2% damping ratio
alphaM = 0.0  # M-prop. damping; D = alphaM*M
betaKcurr = 0.0  # K-proportional damping;      +beatKcurr*KCurrent
betaKinit = 0.0  # initial-stiffness proportional damping      +beatKinit*Kini

op.rayleigh(alphaM, betaKcurr, betaKinit, betaKcomm)  # RAYLEIGH damping

# Uniform EXCITATION: acceleration input
IDloadTag = 400  # load tag
dt = 0.01  # time step for input ground motion
GMfatt = 1.0  # data in input file is in g Unifts -- ACCELERATION TH
maxNumIter = 10
# Create the solution algorithm, a Newton-Raphson algorithm
ops.algorithm('Newton')

# Create the DOF numberer, the reverse Cuthill-McKee algorithm
ops.numberer('RCM')

# Create the integration scheme, the Newmark with alpha =0.5 and beta =.25
ops.integrator('Newmark', 0.5, 0.25)

# Create the analysis object
ops.analysis('Transient')

# Perform an eigenvalue analysis
numEigen = 2
eigenValues = ops.eigen(numEigen)
print("eigen values at start of transient:", eigenValues)

# set some variables
tFinal = nPts * dt
tCurrent = ops.getTime()
ok = 0

time = [tCurrent]
u3 = [0.0]

# Perform the transient analysis
while ok == 0 and tCurrent < tFinal:

    ok = ops.analyze(1, .01)
Exemple #6
0
def test_PortalFrame2d():

    # set some properties
    print("================================================")
    print("PortalFrame2d.py: Verification 2d Elastic Frame")
    print("  - eigenvalue and static pushover analysis")

    ops.wipe()

    ops.model('Basic', '-ndm', 2)

    # properties

    #    units kip, ft

    numBay = 2
    numFloor = 7

    bayWidth = 360.0
    storyHeights = [162.0, 162.0, 156.0, 156.0, 156.0, 156.0, 156.0]

    E = 29500.0
    massX = 0.49
    M = 0.
    coordTransf = "Linear"  # Linear, PDelta, Corotational
    massType = "-lMass"  # -lMass, -cMass

    beams = [
        'W24X160', 'W24X160', 'W24X130', 'W24X130', 'W24X110', 'W24X110',
        'W24X110'
    ]
    eColumn = [
        'W14X246', 'W14X246', 'W14X246', 'W14X211', 'W14X211', 'W14X176',
        'W14X176'
    ]
    iColumn = [
        'W14X287', 'W14X287', 'W14X287', 'W14X246', 'W14X246', 'W14X211',
        'W14X211'
    ]
    columns = [eColumn, iColumn, eColumn]

    WSection = {
        'W14X176': [51.7, 2150.],
        'W14X211': [62.1, 2670.],
        'W14X246': [72.3, 3230.],
        'W14X287': [84.4, 3910.],
        'W24X110': [32.5, 3330.],
        'W24X130': [38.3, 4020.],
        'W24X160': [47.1, 5120.]
    }

    nodeTag = 1

    # procedure to read
    def ElasticBeamColumn(eleTag, iNode, jNode, sectType, E, transfTag, M,
                          massType):

        found = 0

        prop = WSection[sectType]

        A = prop[0]
        I = prop[1]
        ops.element('elasticBeamColumn', eleTag, iNode, jNode, A, E, I,
                    transfTag, '-mass', M, massType)

    # add the nodes
    #  - floor at a time
    yLoc = 0.
    for j in range(0, numFloor + 1):

        xLoc = 0.
        for i in range(0, numBay + 1):
            ops.node(nodeTag, xLoc, yLoc)
            xLoc += bayWidth
            nodeTag += 1

        if j < numFloor:
            storyHeight = storyHeights[j]

        yLoc += storyHeight

    # fix first floor
    ops.fix(1, 1, 1, 1)
    ops.fix(2, 1, 1, 1)
    ops.fix(3, 1, 1, 1)

    #rigid floor constraint & masses
    nodeTagR = 5
    nodeTag = 4
    for j in range(1, numFloor + 1):
        for i in range(0, numBay + 1):

            if nodeTag != nodeTagR:
                ops.equalDOF(nodeTagR, nodeTag, 1)
            else:
                ops.mass(nodeTagR, massX, 1.0e-10, 1.0e-10)

            nodeTag += 1

        nodeTagR += numBay + 1

    # add the columns
    # add column element
    ops.geomTransf(coordTransf, 1)
    eleTag = 1
    for j in range(0, numBay + 1):

        end1 = j + 1
        end2 = end1 + numBay + 1
        thisColumn = columns[j]

        for i in range(0, numFloor):
            secType = thisColumn[i]
            ElasticBeamColumn(eleTag, end1, end2, secType, E, 1, M, massType)
            end1 = end2
            end2 += numBay + 1
            eleTag += 1

    # add beam elements
    for j in range(1, numFloor + 1):
        end1 = (numBay + 1) * j + 1
        end2 = end1 + 1
        secType = beams[j - 1]
        for i in range(0, numBay):
            ElasticBeamColumn(eleTag, end1, end2, secType, E, 1, M, massType)
            end1 = end2
            end2 = end1 + 1
            eleTag += 1

    # calculate eigenvalues & print results
    numEigen = 7
    eigenValues = ops.eigen(numEigen)
    PI = 2 * asin(1.0)

    #
    # apply loads for static analysis & perform analysis
    #

    ops.timeSeries('Linear', 1)
    ops.pattern('Plain', 1, 1)
    ops.load(22, 20.0, 0., 0.)
    ops.load(19, 15.0, 0., 0.)
    ops.load(16, 12.5, 0., 0.)
    ops.load(13, 10.0, 0., 0.)
    ops.load(10, 7.5, 0., 0.)
    ops.load(7, 5.0, 0., 0.)
    ops.load(4, 2.5, 0., 0.)

    ops.integrator('LoadControl', 1.0)
    ops.algorithm('Linear')
    ops.analysis('Static')
    ops.analyze(1)

    # determine PASS/FAILURE of test
    ok = 0

    #
    # print pretty output of comparsions
    #

    #               SAP2000   SeismoStruct
    comparisonResults = [[
        1.2732, 0.4313, 0.2420, 0.1602, 0.1190, 0.0951, 0.0795
    ], [1.2732, 0.4313, 0.2420, 0.1602, 0.1190, 0.0951, 0.0795]]
    print("\n\nPeriod Comparisons:")
    print('{:>10}{:>15}{:>15}{:>15}'.format('Period', 'OpenSees', 'SAP2000',
                                            'SeismoStruct'))

    #formatString {%10s%15.5f%15.4f%15.4f}
    for i in range(0, numEigen):
        lamb = eigenValues[i]
        period = 2 * PI / sqrt(lamb)
        print('{:>10}{:>15.5f}{:>15.4f}{:>15.4f}'.format(
            i + 1, period, comparisonResults[0][i], comparisonResults[1][i]))
        resultOther = comparisonResults[0][i]
        if abs(period - resultOther) > 9.99e-5:
            ok = -1

    # print table of camparsion
    #       Parameter          SAP2000   SeismoStruct
    comparisonResults = [[
        "Disp Top", "Axial Force Bottom Left", "Moment Bottom Left"
    ], [1.45076, 69.99, 2324.68], [1.451, 70.01, 2324.71]]
    tolerances = [9.99e-6, 9.99e-3, 9.99e-3]

    print("\n\nSatic Analysis Result Comparisons:")
    print('{:>30}{:>15}{:>15}{:>15}'.format('Parameter', 'OpenSees', 'SAP2000',
                                            'SeismoStruct'))
    for i in range(3):
        response = ops.eleResponse(1, 'forces')
        if i == 0:
            result = ops.nodeDisp(22, 1)
        elif i == 1:
            result = abs(response[1])
        else:
            result = response[2]

        print('{:>30}{:>15.3f}{:>15.2f}{:>15.2f}'.format(
            comparisonResults[0][i], result, comparisonResults[1][i],
            comparisonResults[2][i]))
        resultOther = comparisonResults[1][i]
        tol = tolerances[i]
        if abs(result - resultOther) > tol:
            ok = -1
            print("failed-> ", i, abs(result - resultOther), tol)

    assert ok == 0
Exemple #7
0
def test_Ex1aCanti2DEQmodif():
    # SET UP ----------------------------------------------------------------------------
    ops.wipe()  # clear opensees model
    ops.model('basic', '-ndm', 2, '-ndf', 3)  # 2 dimensions, 3 dof per node
    # file mkdir data 				   # create data directory

    # define GEOMETRY -------------------------------------------------------------
    # nodal coordinates:
    ops.node(1, 0., 0.)  # node#, X Y
    ops.node(2, 0., 432.)

    # Single point constraints -- Boundary Conditions
    ops.fix(1, 1, 1, 1)  # node DX DY RZ

    # nodal masses:
    ops.mass(2, 5.18, 0., 0.)  # node#, Mx My Mz, Mass=Weight/g.

    # Define ELEMENTS -------------------------------------------------------------
    # define geometric transformation: performs a linear geometric transformation of beam stiffness and resisting force from the basic system to the global-coordinate system
    ops.geomTransf('Linear', 1)  # associate a tag to transformation

    # connectivity:
    ops.element('elasticBeamColumn', 1, 1, 2, 3600.0, 3225.0, 1080000.0, 1)

    # define GRAVITY -------------------------------------------------------------
    ops.timeSeries('Linear', 1)
    ops.pattern(
        'Plain',
        1,
        1,
    )
    ops.load(2, 0., -2000., 0.)  # node#, FX FY MZ --  superstructure-weight

    ops.constraints('Plain')  # how it handles boundary conditions
    ops.numberer(
        'Plain'
    )  # renumber dof's to minimize band-width (optimization), if you want to
    ops.system(
        'BandGeneral'
    )  # how to store and solve the system of equations in the analysis
    ops.algorithm('Linear')  # use Linear algorithm for linear analysis
    ops.integrator(
        'LoadControl', 0.1
    )  # determine the next time step for an analysis, # apply gravity in 10 steps
    ops.analysis('Static')  # define type of analysis static or transient
    ops.analyze(10)  # perform gravity analysis
    ops.loadConst('-time', 0.0)  # hold gravity constant and restart time

    # DYNAMIC ground-motion analysis -------------------------------------------------------------
    # create load pattern
    G = 386.0
    ops.timeSeries(
        'Path', 2, '-dt', 0.005, '-filePath', 'A10000.dat', '-factor', G
    )  # define acceleration vector from file (dt=0.005 is associated with the input file gm)
    ops.pattern(
        'UniformExcitation', 2, 1, '-accel',
        2)  # define where and how (pattern tag, dof) acceleration is applied

    # set damping based on first eigen mode
    evals = ops.eigen('-fullGenLapack', 1)
    freq = evals[0]**0.5
    dampRatio = 0.02
    ops.rayleigh(0., 0., 0., 2 * dampRatio / freq)

    # display displacement shape of the column
    # recorder display "Displaced shape" 10 10 500 500 -wipe
    # prp 200. 50. 1
    # vup  0  1 0
    # vpn  0  0 1
    # display 1 5 40

    # create the analysis
    ops.wipeAnalysis()  # clear previously-define analysis parameters
    ops.constraints('Plain')  # how it handles boundary conditions
    ops.numberer(
        'Plain'
    )  # renumber dof's to minimize band-width (optimization), if you want to
    ops.system(
        'BandGeneral'
    )  # how to store and solve the system of equations in the analysis
    ops.algorithm('Linear')  # use Linear algorithm for linear analysis
    ops.integrator('Newmark', 0.5,
                   0.25)  # determine the next time step for an analysis
    ops.analysis('Transient')  # define type of analysis: time-dependent
    ops.analyze(3995, 0.01)  # apply 3995 0.01-sec time steps in analysis

    u2 = ops.nodeDisp(2, 2)
    print("u2 = ", u2)

    assert abs(u2 + 0.07441860465116277579) < 1e-12
    ops.wipe()

    print("=========================================")
Exemple #8
0
def ModalAnalysis3D(numEigen):
    """
    |-----------------------------------------------------------------------|
    |                                                                       |
    |    Modal Analysis of 3D systems                                       |
    |                                                                       |
    |    Author: Volkan Ozsarac                                             |
    |    Affiliation: University School for Advanced Studies IUSS Pavia     |
    |    Earthquake Engineering PhD Candidate                               |
    |                                                                       |
    |-----------------------------------------------------------------------|
    """
    import numpy as np
    import openseespy.opensees as op
    import time
    import sys

    print('Extracting the mass matrix, ignore the following warnings...\n')
    op.wipeAnalysis()
    op.system('FullGeneral')
    op.analysis('Transient')

    # Extract the Mass Matrix
    op.integrator('GimmeMCK',1.0,0.0,0.0)
    op.analyze(1,0.0) 
    time.sleep(0.5) 
    # Number of equations in the model
    N = op.systemSize() # Has to be done after analyze
    Mmatrix = op.printA('-ret') # Or use op.printA('-file','M.out')
    Mmatrix = np.array(Mmatrix) # Convert the list to an array
    Mmatrix.shape = (N,N) # Make the array an NxN matrix
    print('\nExtracted the mass matrix, ignore the previous warnings...')

    # Rerrange the mass matrix in accordance with nodelist order from getNodeTags()
    DOFs = [] # These are the idx of all the DOFs used in the extract mass matrix, order is rearranged
    used = {} # Save here the nodes and their associated dofs used in global mass matrix
    lx = np.zeros([N,1]) # influence vector (x)
    ly = np.zeros([N,1]) # influence vector (y)
    lz = np.zeros([N,1]) # influence vector (z)
    lrx = np.zeros([N,1]) # influence vector (rx)
    lry = np.zeros([N,1]) # influence vector (ry)
    lrz = np.zeros([N,1]) # influence vector (rz)

    idx = 0 # index
    NDF = 6 # NDF is number of DOFs/node
    for node in op.getNodeTags():
        used[node] = []
        for j in range(NDF): 
            temp = op.nodeDOFs(node)[j]
            if temp not in DOFs and temp >=0:
                DOFs.append(op.nodeDOFs(node)[j])
                used[node].append(j+1)
                if j == 0: lx[idx,0] = 1
                if j == 1: ly[idx,0] = 1
                if j == 2: lz[idx,0] = 1
                if j == 3: lrx[idx,0] = 1
                if j == 4: lry[idx,0] = 1
                if j == 5: lrz[idx,0] = 1
                idx += 1

    Mmatrix = Mmatrix[DOFs,:][:,DOFs] 

    op.wipeAnalysis()
    listSolvers = ['-genBandArpack','-fullGenLapack','-symmBandLapack']
    ok = 1  

    for s in listSolvers:
        print("Using %s as solver..." % s[1:])
        try:
            eigenValues = op.eigen(s,numEigen)
            catchOK = 0
            ok = 0
        except: 
            catchOK = 1

        if catchOK==0:
            for i in range(numEigen):
                if eigenValues[i] < 0: ok = 1
            if ok==0: 
                print('Eigenvalue analysis is completed.')
                break

    if ok!=0:
        print("Error on Modal Analysis...")
        sys.exit()
    else:  
        Lamda = np.asarray(eigenValues)
        Omega = Lamda**0.5
        T = 2*np.pi/Omega
        f = 1/T

    print('Modal properties for the first %d modes:' % numEigen)
    Mx = []; My = []; Mz = []; Mrx = []; Mry = []; Mrz = []
    dofs = ['x','y','z','rx','ry','rz']
    print('Mode| T [sec] | f [Hz] | \u03C9 [rad/sec] | Mx [%] | My [%] | Mz [%] | \u2211Mx [%] | \u2211My [%] | \u2211Mz [%]')

    for mode in range(1,numEigen+1): # Although Mrx, Mry and Mrz are calculated, I am not printing these
        idx = 0
        phi = np.zeros([N,1])
        for node in used:
            for dof in used[node]:
                phi[idx,0]=op.nodeEigenvector(node,mode,dof)
                idx += 1
        
        for dof in dofs:
            l = eval('l'+dof)
            Mtot = l.T@Mmatrix@l   # Total mass in specified global dof
            Mn = phi.T@Mmatrix@phi # Modal mass in specified global dof
            Ln = phi.T@Mmatrix@l   # Effective modal mass in specified global dof
            Mnstar = Ln**2/Mn/Mtot*100 # Normalised effective modal mass participating [%], in specified global dof
            eval('M'+dof).append(Mnstar[0,0]) # Save the modal mass for the specified dof
        
        print('%3s |%7s  |%6s  |%9s    |%6s  |%6s  |%6s  |%7s  |%7s  |%7s' \
              % ("{:.0f}".format(mode), "{:.3f}".format(T[mode-1]), "{:.3f}".format(f[mode-1]), "{:.2f}".format(Omega[mode-1]), \
                  "{:.2f}".format(Mx[mode-1]), "{:.2f}".format(My[mode-1]), "{:.2f}".format(Mz[mode-1]), \
                  "{:.2f}".format(sum(Mx)), "{:.2f}".format(sum(My)), "{:.2f}".format(sum(Mz))))

    Mtot = lx.T@Mmatrix@lx; Mtot = Mtot[0,0]
    def __init__(self):
        # AIが取れるアクションの設定
        self.action = np.array([
            0, 0.02, 0.03, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1
        ])
        self.naction = len(self.action)

        self.beta = 1 / 4

        # 1質点系モデル
        self.T0 = 4
        self.h = self.action[0]
        self.hs = [self.h]
        self.m = 100
        self.k = 4 * np.pi**2 * self.m / self.T0**2

        # 入力地震動
        self.dt = 0.02
        to_meter = 0.01  # cmをmに変換する値
        self.wave_url = 'https://github.com/kakemotokeita/dqn-seismic-control/blob/master/wave/sample.csv'
        with urllib.request.urlopen(self.wave_url) as wave_file:
            self.wave_data = np.loadtxt(
                wave_file, usecols=(0, ), delimiter=',', skiprows=3) * to_meter

        # OpenSees設定
        op.wipe()
        op.model('basic', '-ndm', 2, '-ndf', 3)  # 2 dimensions, 3 dof per node

        # 節点
        self.bot_node = 1
        self.top_node = 2
        op.node(self.bot_node, 0., 0.)
        op.node(self.top_node, 0., 0.)

        # 境界条件
        op.fix(self.top_node, FREE, FIXED, FIXED)
        op.fix(self.bot_node, FIXED, FIXED, FIXED)
        op.equalDOF(1, 2, *[Y, ROTZ])

        # 質量
        op.mass(self.top_node, self.m, 0., 0.)

        # 弾性剛性
        elastic_mat_tag = 1
        Fy = 1e10
        E0 = self.k
        b = 1.0
        op.uniaxialMaterial('Steel01', elastic_mat_tag, Fy, E0, b)

        # Assign zero length element
        beam_tag = 1
        op.element('zeroLength', beam_tag, self.bot_node, self.top_node,
                   "-mat", elastic_mat_tag, "-dir", 1, '-doRayleigh', 1)

        # Define the dynamic analysis
        load_tag_dynamic = 1
        pattern_tag_dynamic = 1

        self.values = list(-1 * self.wave_data)  # should be negative
        op.timeSeries('Path', load_tag_dynamic, '-dt', self.dt, '-values',
                      *self.values)
        op.pattern('UniformExcitation', pattern_tag_dynamic, X, '-accel',
                   load_tag_dynamic)

        # 減衰の設定
        self.w0 = op.eigen('-fullGenLapack', 1)[0]**0.5
        self.alpha_m = 0.0
        self.beta_k = 2 * self.h / self.w0
        self.beta_k_init = 0.0
        self.beta_k_comm = 0.0

        op.rayleigh(self.alpha_m, self.beta_k, self.beta_k_init,
                    self.beta_k_comm)

        # Run the dynamic analysis

        op.wipeAnalysis()

        op.algorithm('Newton')
        op.system('SparseGeneral')
        op.numberer('RCM')
        op.constraints('Transformation')
        op.integrator('Newmark', 0.5, 0.25)
        op.analysis('Transient')

        tol = 1.0e-10
        iterations = 10
        op.test('EnergyIncr', tol, iterations, 0, 2)
        self.i_pre = 0
        self.i = 0
        self.i_next = 0
        self.time = 0
        self.analysis_time = (len(self.values) - 1) * self.dt
        self.dis = 0
        self.vel = 0
        self.acc = 0
        self.a_acc = 0
        self.force = 0
        self.resp = {
            "time": [],
            "dis": [],
            "acc": [],
            "a_acc": [],
            "vel": [],
            "force": [],
        }
        self.done = False
Exemple #10
0
def build_model(model_params):
    """
    Generates OpenSeesPy model of an elastic cantilever and runs gravity analysis.

    Assumes that length is measured in inches and acceleration in in/s2

    Parameters
    ----------
    NumberOfStories: int
        Number of stories
    StructureType: string
        Type of structural system - expects one of the HAZUS structure classes
    PlanArea: float
        Area of the structure's footprint

    """

    # Assumptions
    h_story = 12  # Story height [ft]
    w_story = 200  # Story weight [psf]

    # constants for unit conversion
    ft = 1.0
    inch = 12.0
    m = 3.28084

    ft2 = 1.0
    inch2 = inch**2.
    m2 = m**2.

    psf = 1.0
    Nsm = 4.88242  # N per square meter

    stories = model_params["NumberOfStories"]
    node_tags = list(range(stories + 1))

    # The fundamental period is approximated as per ASCE 7-16 12.8.2.1
    h_n = stories * h_story  # [ft]

    if model_params['StructureType'] in [
            'S1',
    ]:
        # steel moment-resisting frames
        C_t = 0.028
        x = 0.8

    elif model_params['StructureType'] in [
            'C1',
    ]:
        # concrete moment-resisting frames
        C_t = 0.016
        x = 0.9

    elif model_params['StructureType'] in ['BRBF', 'ECBF']:
        # steel eccentrically braced frames or
        # steel buckling-restrained braced frame
        C_t = 0.03
        x = 0.75

    else:
        C_t = 0.02
        x = 0.75

    T1 = C_t * h_n**x  # Eq 12.8-7 in ASCE 7-16

    # check the units
    units = model_params["units"]

    if 'length' in units.keys():

        if units['length'] == 'm':
            G = 9.81
            h_story = h_story * m
            w_story = w_story * Nsm

        elif units['length'] == 'ft':
            G = 32.174
            h_story = h_story * ft
            w_story = w_story / ft2

        else:  # elif units['length'] == 'in':
            G = 386.1
            h_story = h_story * inch
            w_story = w_story / inch2

    # The weight at each story is assumed to be identical
    W = model_params["PlanArea"] * w_story

    m = W / G

    # We calculate stiffness assuming half of the mass vibrates at the top
    K = ((m * stories) / 2.) / (T1 / (2 * pi))**2.

    # set model dimensions and degrees of freedom
    ops.model('basic', '-ndm', 3, '-ndf', 6)

    # define an elastic and a rigid material
    elastic_tag = 100
    rigid_tag = 110
    ops.uniaxialMaterial('Elastic', elastic_tag, K)
    ops.uniaxialMaterial('Elastic', rigid_tag, 1.e9)

    # define pattern for gravity loads
    ops.timeSeries('Linear', 1)
    ops.pattern('Plain', 101, 1)

    for story in range(0, stories + 1):

        # define nodes
        ops.node(node_tags[story], 0., 0., story * h_story)

        # define fixities
        if story == 0:
            ops.fix(node_tags[0], 1, 1, 1, 1, 1, 1)
        else:
            ops.fix(node_tags[story], 0, 0, 0, 1, 1, 1)

        # define elements
        if story > 0:
            element_tag = 1000 + story - 1
            ops.element('twoNodeLink', element_tag, node_tags[story - 1],
                        node_tags[story], '-mat', rigid_tag, elastic_tag,
                        elastic_tag, '-dir', 1, 2, 3, '-orient', 0., 0., 1.,
                        0., 1., 0., '-doRayleigh')

            # define masses
            ops.mass(node_tags[story], m, m, m, 0., 0., 0.)

            # define loads
            ops.load(node_tags[story], 0., 0., -W, 0., 0., 0.)

    # define damping based on first eigenmode
    damp_ratio = 0.05
    angular_freq = ops.eigen(1)[0]**0.5
    beta_k = 2 * damp_ratio / angular_freq
    ops.rayleigh(0., beta_k, 0., 0.)

    # run gravity analysis
    tol = 1e-8  # convergence tolerance for test
    iter = 100  # max number of iterations
    nstep = 100  # apply gravity loads in 10 steps
    incr = 1. / nstep  # first load increment

    # analysis settings
    ops.constraints(
        'Transformation'
    )  # enforce boundary conditions using transformation constraint handler
    ops.numberer(
        'RCM')  # renumbers dof's to minimize band-width (optimization)
    ops.system(
        'BandGeneral'
    )  # stores system of equations as 1D array of size bandwidth x number of unknowns
    ops.test(
        'EnergyIncr', tol, iter, 0
    )  # tests for convergence using dot product of solution vector and norm of right-hand side of matrix equation
    ops.algorithm(
        'Newton'
    )  # use Newton's solution algorithm: updates tangent stiffness at every iteration
    ops.integrator(
        'LoadControl', incr
    )  # determine the next time step for an analysis # apply gravity in 10 steps
    ops.analysis('Static')  # define type of analysis, static or transient
    ops.analyze(nstep)  # perform gravity analysis

    # after gravity analysis, change time and tolerance for the dynamic analysis
    ops.loadConst('-time', 0.0)
Exemple #11
0
def get_inelastic_response(mass,
                           k_spring,
                           f_yield,
                           motion,
                           dt,
                           xi=0.05,
                           r_post=0.0):
    """
    Run seismic analysis of a nonlinear SDOF

    :param mass: SDOF mass
    :param k_spring: spring stiffness
    :param f_yield: yield strength
    :param motion: list, acceleration values
    :param dt: float, time step of acceleration values
    :param xi: damping ratio
    :param r_post: post-yield stiffness
    :return:
    """
    osi = o3.OpenSeesInstance(ndm=2)

    # Establish nodes
    bot_node = o3.node.Node(osi, 0, 0)
    top_node = o3.node.Node(osi, 0, 0)

    # Fix bottom node
    opy.fix(top_node.tag, o3.cc.FREE, o3.cc.FIXED, o3.cc.FIXED)
    opy.fix(bot_node.tag, o3.cc.FIXED, o3.cc.FIXED, o3.cc.FIXED)
    # Set out-of-plane DOFs to be slaved
    opy.equalDOF(top_node.tag, bot_node.tag, *[o3.cc.Y, o3.cc.ROTZ])

    # nodal mass (weight / g):
    opy.mass(top_node.tag, mass, 0., 0.)

    # Define material
    bilinear_mat = o3.uniaxial_material.Steel01(osi,
                                                fy=f_yield,
                                                e0=k_spring,
                                                b=r_post)

    # Assign zero length element, # Note: pass actual node and material objects into element
    o3.element.ZeroLength(osi, [bot_node, top_node],
                          mats=[bilinear_mat],
                          dirs=[o3.cc.DOF2D_X],
                          r_flag=1)

    # Define the dynamic analysis
    load_tag_dynamic = 1
    pattern_tag_dynamic = 1

    values = list(-1 * motion)  # should be negative
    opy.timeSeries('Path', load_tag_dynamic, '-dt', dt, '-values', *values)
    opy.pattern('UniformExcitation', pattern_tag_dynamic, o3.cc.X, '-accel',
                load_tag_dynamic)

    # set damping based on first eigen mode
    angular_freq2 = opy.eigen('-fullGenLapack', 1)
    if hasattr(angular_freq2, '__len__'):
        angular_freq2 = angular_freq2[0]
    angular_freq = angular_freq2**0.5
    beta_k = 2 * xi / angular_freq
    o3.rayleigh.Rayleigh(osi,
                         alpha_m=0.0,
                         beta_k=beta_k,
                         beta_k_init=0.0,
                         beta_k_comm=0.0)

    # Run the dynamic analysis

    opy.wipeAnalysis()
    newmark_gamma = 0.5
    newmark_beta = 0.25

    o3.algorithm.Newton(osi)
    o3.constraints.Transformation(osi)
    o3.algorithm.Newton(osi)
    o3.numberer.RCM(osi)
    o3.system.SparseGeneral(osi)
    o3.integrator.Newmark(osi, newmark_gamma, newmark_beta)
    o3.analysis.Transient(osi)

    o3.test_check.EnergyIncr(osi, tol=1.0e-10, max_iter=10)
    analysis_time = (len(values) - 1) * dt
    analysis_dt = 0.001
    outputs = {
        "time": [],
        "rel_disp": [],
        "rel_accel": [],
        "rel_vel": [],
        "force": []
    }

    while opy.getTime() < analysis_time:
        curr_time = opy.getTime()
        opy.analyze(1, analysis_dt)
        outputs["time"].append(curr_time)
        outputs["rel_disp"].append(opy.nodeDisp(top_node.tag, o3.cc.X))
        outputs["rel_vel"].append(opy.nodeVel(top_node.tag, o3.cc.X))
        outputs["rel_accel"].append(opy.nodeAccel(top_node.tag, o3.cc.X))
        opy.reactions()
        outputs["force"].append(-opy.nodeReaction(
            bot_node.tag, o3.cc.X))  # Negative since diff node
    opy.wipe()
    for item in outputs:
        outputs[item] = np.array(outputs[item])

    return outputs
Exemple #12
0
    def createOutputDatabase(self, Nmodes=0, deltaT=0.0, recorders=[]):
        """
        This function creates a directory to save all the output data.
    
        Command: createODB("ModelName",<"LoadCase Name">, <Nmodes=Nmodes(int)>, <recorders=*recorder(list)>)
        
        ModelName    : (string) Name of the model. The main output folder will be named "ModelName_ODB" in the current directory.
        LoadCase Name: (string), Optional. Name of the load case forder to be created inside the ModelName_ODB folder. If not provided,
                        no load case data will be read.
        Nmodes         : (int) Optional key argument to save modeshape data. Default is 0, no modeshape data is saved.
        
        deltaT         : (float) Optional time interval for recording. will record when next step is deltaT greater than last recorder step. 
                        (default: records at every time step)
        
        recorders     : (string) A list of additional quantities a users would like to record in the output database.
                        The arguments for these additional inputs match the standard OpenSees arguments to avoid any confusion.
                        'localForce','basicDeformation', 'plasticDeformation','stresses','strains'
                        The recorders for node displacement and reactions are saved by default to help plot the deformed shape.
        
        Example: createODB(TwoSpanBridge, Pushover, Nmodes=3, recorders=['stresses', 'strains'])
        
        Future: The integrationPoints output works only for nonlinear beam column elements. If a model has a combination 
                of elastic and nonlienar elements, we need to create a method distinguish. 
        
        """

        ODBdir = self.ODBdir  # ODB Dir name
        if not os.path.exists(ODBdir):
            os.makedirs(ODBdir)

        nodeList = op.getNodeTags()
        eleList = op.getEleTags()

        dofList = [int(ii + 1) for ii in range(len(op.nodeCoord(nodeList[0])))]

        # Save node and element data in the main Output folder
        self.saveNodesandElements()

        #########################
        ## Create mode shape dir
        #########################
        if Nmodes > 0:
            ModeShapeDir = os.path.join(ODBdir, "ModeShapes")
            if not os.path.exists(ModeShapeDir):
                os.makedirs(ModeShapeDir)

            ## Run eigen analysis internally and get information to print
            Tarray = np.zeros([1,
                               Nmodes])  # To save all the periods of vibration
            op.wipeAnalysis()
            eigenVal = op.eigen(Nmodes + 1)

            for mm in range(1, Nmodes + 1):
                Tarray[0, mm - 1] = 4 * asin(1.0) / (eigenVal[mm - 1])**0.5

            modeTFile = os.path.join(ModeShapeDir, "ModalPeriods.out")
            np.savetxt(modeTFile, Tarray, delimiter=self.delim, fmt=self.fmt)

            ### Save mode shape data
            for ii in range(1, Nmodes + 1):
                self.saveModeShapeData(ii)

            op.wipeAnalysis()

        LoadCaseDir = self.LoadCaseDir

        if not os.path.exists(LoadCaseDir):
            os.makedirs(LoadCaseDir)

        NodeDispFile = os.path.join(LoadCaseDir, "NodeDisp_All.out")
        EleForceFile = os.path.join(LoadCaseDir, "EleForce_All.out")
        ReactionFile = os.path.join(LoadCaseDir, "Reaction_All.out")
        EleStressFile = os.path.join(LoadCaseDir, "EleStress_All.out")
        EleStrainFile = os.path.join(LoadCaseDir, "EleStrain_All.out")
        EleBasicDefFile = os.path.join(LoadCaseDir, "EleBasicDef_All.out")
        ElePlasticDefFile = os.path.join(LoadCaseDir, "ElePlasticDef_All.out")
        # EleIntPointsFile = os.path.join(LoadCaseDir,"EleIntPoints_All.out")

        # Save recorders in the ODB folder
        op.recorder('Node', '-file', NodeDispFile, '-time', '-dT', deltaT,
                    '-node', *nodeList, '-dof', *dofList, 'disp')
        op.recorder('Node', '-file', ReactionFile, '-time', '-dT', deltaT,
                    '-node', *nodeList, '-dof', *dofList, 'reaction')

        if 'localForce' in recorders:
            op.recorder('Element', '-file', EleForceFile, '-time', '-dT',
                        deltaT, '-ele', *eleList, '-dof', *dofList,
                        'localForce')

        if 'basicDeformation' in recorders:
            op.recorder('Element', '-file', EleBasicDefFile, '-time', '-dT',
                        deltaT, '-ele', *eleList, '-dof', *dofList,
                        'basicDeformation')

        if 'plasticDeformation' in recorders:
            op.recorder('Element', '-file', ElePlasticDefFile, '-time', '-dT',
                        deltaT, '-ele', *eleList, '-dof', *dofList,
                        'plasticDeformation')

        if 'stresses' in recorders:
            op.recorder('Element', '-file', EleStressFile, '-time', '-dT',
                        deltaT, '-ele', *eleList, 'stresses')

        if 'strains' in recorders:
            op.recorder('Element', '-file', EleStrainFile, '-time', '-dT',
                        deltaT, '-ele', *eleList, 'strains')
Exemple #13
0
def test_EigenFrame():
    ops.wipe()

    ops.model('Basic', '-ndm', 2)

    #    units kip, ft

    # properties
    bayWidth = 20.0
    storyHeight = 10.0

    numBay = 10
    numFloor = 9
    A = 3.0  #area = 3ft^2
    E = 432000.0  #youngs mod = 432000 k/ft^2
    I = 1.0  #second moment of area I=1ft^4
    M = 3.0  #mas/length = 4 kip sec^2/ft^2
    coordTransf = "Linear"  # Linear, PDelta, Corotational
    massType = "-lMass"  # -lMass, -cMass

    # add the nodes
    #  - floor at a time
    nodeTag = 1
    yLoc = 0.
    for j in range(0, numFloor + 1):
        xLoc = 0.
        for i in range(0, numBay + 1):
            ops.node(nodeTag, xLoc, yLoc)
            xLoc += bayWidth
            nodeTag += 1

        yLoc += storyHeight

    # fix base nodes
    for i in range(1, numBay + 2):
        ops.fix(i, 1, 1, 1)

    # add column element
    ops.geomTransf(coordTransf, 1)
    eleTag = 1
    for i in range(0, numBay + 1):
        end1 = i + 1
        end2 = end1 + numBay + 1
        for j in range(0, numFloor):
            ops.element('elasticBeamColumn', eleTag, end1, end2, A, E, I, 1,
                        '-mass', M, massType)
            end1 = end2
            end2 = end1 + numBay + 1
            eleTag += 1

    # add beam elements
    for j in range(1, numFloor + 1):
        end1 = (numBay + 1) * j + 1
        end2 = end1 + 1
        for i in range(0, numBay):
            ops.element('elasticBeamColumn', eleTag, end1, end2, A, E, I, 1,
                        '-mass', M, massType)
            end1 = end2
            end2 = end1 + 1
            eleTag += 1

    # calculate eigenvalues
    numEigen = 3
    eigenValues = ops.eigen(numEigen)
    PI = 2 * asin(1.0)

    #recorder('PVD','EigenFrame','eigen',numEigen)
    #record()

    # determine PASS/FAILURE of test
    testOK = 0

    # print table of camparsion
    #                         Bathe & Wilson               Peterson                    SAP2000                  SeismoStruct
    comparisonResults = [[0.589541, 5.52695, 16.5878],
                         [0.589541, 5.52696, 16.5879],
                         [0.589541, 5.52696, 16.5879],
                         [0.58955, 5.527, 16.588]]
    print("\n\nEigenvalue Comparisons:")
    tolerances = [9.99e-6, 9.99e-6,
                  9.99e-5]  # tolerances prescribed by documented precision
    formatString = '{:>15}{:>15}{:>15}{:>15}{:>15}'
    print(
        formatString.format('OpenSees', 'Bathe&Wilson', 'Peterson', 'SAP2000',
                            'SeismoStruct'))
    formatString = '{:>15.5f}{:>15.4f}{:>15.4f}{:>15.4f}{:>15.3f}'
    for i in range(0, numEigen):
        lamb = eigenValues[i]
        print(
            formatString.format(lamb, comparisonResults[0][i],
                                comparisonResults[1][i],
                                comparisonResults[2][i],
                                comparisonResults[3][i]))
        resultOther = comparisonResults[2][i]
        tol = tolerances[i]
        if abs(lamb - resultOther) > tol:
            testOK = -1
            print("failed->", abs(lamb - resultOther), tol)

    assert testOK == 0
Exemple #14
0
def test_DynAnal_BeamWithQuadElements():

    ops.wipe()  # clear opensees model

    # create data directory
    # file mkdir Data

    #-----------------------------
    # Define the model
    # ----------------------------

    # Create ModelBuilder with 2 dimensions and 2 DOF/node
    ops.model('BasicBuilder', '-ndm', 2, '-ndf', 2)

    # create the material
    ops.nDMaterial('ElasticIsotropic', 1, 1000.0, 0.25, 3.0)

    # set type of quadrilateral element (uncomment one of the three options)
    Quad = 'quad'
    #set Quad bbarQuad
    #set Quad enhancedQuad

    # set up the arguments for the three considered elements
    if Quad == "enhancedQuad":
        eleArgs = "PlaneStress2D 1"

    if Quad == "quad":
        eleArgs = "1 PlaneStress2D 1"

    if Quad == "bbarQuad":
        eleArgs = "1"

    # set up the number of elements in x (nx) and y (ny) direction
    nx = 16  # NOTE: nx MUST BE EVEN FOR THIS EXAMPLE
    ny = 4

    # define numbering of node at the left support (bn), and the two nodes at load application (l1, l2)
    bn = nx + 1
    l1 = int(nx / 2 + 1)
    l2 = int(l1 + ny * (nx + 1))

    # create the nodes and elements using the block2D command
    ops.block2D(nx, ny, 1, 1, Quad, 1., 'PlaneStress2D', 1, 1, 0., 0., 2, 40.,
                0., 3, 40., 10., 4, 0., 10.)

    # define boundary conditions
    ops.fix(1, 1, 1)
    ops.fix(bn, 0, 1)

    # define the recorder
    #---------------------
    # recorder Node -file Data/Node.out -time -node l1 -dof 2 disp

    # define load pattern
    #---------------------
    ops.timeSeries('Linear', 1)
    ops.pattern('Plain', 1, 1)
    ops.load(l1, 0.0, -1.0)
    ops.load(l2, 0.0, -1.0)

    # --------------------------------------------------------------------
    # Start of static analysis (creation of the analysis & analysis itself)
    # --------------------------------------------------------------------

    # Load control with variable load steps
    #                      init Jd min max
    ops.integrator('LoadControl', 1.0, 1, 1.0, 10.0)

    # Convergence test
    #              tolerance maxIter displayCode
    ops.test('EnergyIncr', 1.0e-12, 10, 0)

    # Solution algorithm
    ops.algorithm('Newton')

    # DOF numberer
    ops.numberer('RCM')

    # Cosntraint handler
    ops.constraints('Plain')

    # System of equations solver
    ops.system('ProfileSPD')

    # Type of analysis analysis
    ops.analysis('Static')

    # Perform the analysis
    ops.analyze(10)

    # --------------------------
    # End of static analysis
    # --------------------------

    # -------------------------------------
    # create display for transient analysis
    #--------------------------------------
    #                    windowTitle       xLoc yLoc xPixels yPixels
    # recorder display "Simply Supported Beam" 10     10      800     200    -wipe
    # prp 20 5.0 1.0                                      # projection reference point (prp) defines the center of projection (viewer eye)
    # vup  0  1 0                                         # view-up vector (vup)
    # vpn  0  0 1                                         # view-plane normal (vpn)
    # viewWindow -30 30 -10 10                            # coordiantes of the window relative to prp
    # display 10 0 5
    # the 1st arg. is the tag for display mode
    # the 2nd arg. is magnification factor for nodes, the 3rd arg. is magnif. factor of deformed shape

    # ---------------------------------------
    # Create and Perform the dynamic analysis
    # ---------------------------------------
    #define damping
    evals = ops.eigen(1)
    ops.rayleigh(0., 0., 0., 2 * 0.02 / sqrt(evals[0]))

    # Remove the static analysis & reset the time to 0.0
    ops.wipeAnalysis()
    ops.setTime(0.0)

    # Now remove the loads and let the beam vibrate
    ops.remove('loadPattern', 1)
    uy1 = ops.nodeDisp(9, 2)
    print("uy(9) = ", uy1)

    # Create the transient analysis
    ops.test('EnergyIncr', 1.0e-12, 10, 0)
    ops.algorithm('Newton')
    ops.numberer('RCM')
    ops.constraints('Plain')
    ops.integrator('Newmark', 0.5, 0.25)
    ops.system('BandGeneral')
    ops.analysis('Transient')

    # Perform the transient analysis (50 sec)
    ops.analyze(1500, 0.5)

    uy2 = ops.nodeDisp(9, 2)
    print("uy(9) = ", uy2)

    assert abs(uy1 + 0.39426414168933876514) < 1e-12 and abs(
        uy2 + 0.00736847273806807632) < 1e-12

    print("========================================")
Exemple #15
0
for step in range(n_steps):
    ops.analyze(1, dt)
    timeV[step] = ops.getTime()
    # collect disp for element nodes
    for el_i, ele_tag in enumerate(el_tags):
        nd1, nd2 = ops.eleNodes(ele_tag)
        Eds[step, el_i, :] = [ops.nodeDisp(nd1)[0],
                              ops.nodeDisp(nd1)[1],
                              ops.nodeDisp(nd1)[2],
                              ops.nodeDisp(nd2)[0],
                              ops.nodeDisp(nd2)[1],
                              ops.nodeDisp(nd2)[2]]

# 1. animate the deformated shape
anim = opsv.anim_defo(Eds, timeV, sfac_a, interpFlag=1, xlim=[-1, 7],
                      ylim=[-1, 5], fig_wi_he=(30., 22.))

plt.show()

# 2. after closing the window, animate the specified mode shape
eigVals = ops.eigen(5)

modeNo = 2  # specify which mode to animate
f_modeNo = np.sqrt(eigVals[modeNo-1])/(2*np.pi)  # i-th natural frequency

anim = opsv.anim_mode(modeNo, interpFlag=1, xlim=[-1, 7], ylim=[-1, 5],
                      fig_wi_he=(30., 22.))
plt.title(f'Mode {modeNo}, f_{modeNo}: {f_modeNo:.3f} Hz')

plt.show()
               nep,
               fmt_interp='b-',
               az_el=(-68., 39.),
               fig_wi_he=fig_wi_he,
               endDispFlag=0)

plt.title('3d 3-element cantilever beam')

# - 2
opsv.plot_defo(sfac, 19, fmt_interp='b-', az_el=(6., 30.), fig_wi_he=fig_wi_he)

plt.title('3d 3-element cantilever beam')

# - 3
nfreq = 6
eigValues = ops.eigen(nfreq)

modeNo = 6

sfac = 2.0e1
opsv.plot_mode_shape(modeNo,
                     sfac,
                     19,
                     fmt_interp='b-',
                     az_el=(106., 46.),
                     fig_wi_he=fig_wi_he)
plt.title(f'Mode {modeNo}')

sfacN = 1.e-2
sfacVy = 5.e-2
sfacVz = 1.e-2
def test_EigenFrameExtra():

    eleTypes = [
        'elasticBeam', 'forceBeamElasticSection', 'dispBeamElasticSection',
        'forceBeamFiberSectionElasticMaterial',
        'dispBeamFiberSectionElasticMaterial'
    ]

    for eleType in eleTypes:

        ops.wipe()

        ops.model('Basic', '-ndm', 2)

        #    units kip, ft

        # properties
        bayWidth = 20.0
        storyHeight = 10.0

        numBay = 10
        numFloor = 9

        A = 3.0  #area = 3ft^2
        E = 432000.0  #youngs mod = 432000 k/ft^2
        I = 1.0  #second moment of area I=1ft^4
        M = 3.0  #mas/length = 4 kip sec^2/ft^2
        coordTransf = "Linear"  # Linear, PDelta, Corotational
        massType = "-lMass"  # -lMass, -cMass

        nPts = 3  # numGauss Points

        # an elastic material
        ops.uniaxialMaterial('Elastic', 1, E)

        # an elastic section
        ops.section('Elastic', 1, E, A, I)

        # a fiber section with A=3 and I = 1 (b=1.5, d=2) 2d bending about y-y axis
        #   b 1.5 d 2.0
        y = 2.0
        z = 1.5
        numFiberY = 2000  # note we only need so many to get the required accuracy on eigenvalue 1e-7!
        numFiberZ = 1
        ops.section('Fiber', 2)
        #   patch rect 1 numFiberY numFiberZ 0.0 0.0 z y
        ops.patch('quad', 1, numFiberY, numFiberZ, -y / 2.0, -z / 2.0, y / 2.0,
                  -z / 2.0, y / 2.0, z / 2.0, -y / 2.0, z / 2.0)

        # add the nodes
        #  - floor at a time
        nodeTag = 1
        yLoc = 0.
        for j in range(0, numFloor + 1):
            xLoc = 0.
            for i in range(numBay + 1):
                ops.node(nodeTag, xLoc, yLoc)
                xLoc += bayWidth
                nodeTag += 1

            yLoc += storyHeight

        # fix base nodes
        for i in range(1, numBay + 2):
            ops.fix(i, 1, 1, 1)

        # add column element
        transfTag = 1
        ops.geomTransf(coordTransf, transfTag)
        integTag1 = 1
        ops.beamIntegration('Lobatto', integTag1, 1, nPts)
        integTag2 = 2
        ops.beamIntegration('Lobatto', integTag2, 2, nPts)
        eleTag = 1
        for i in range(numBay + 1):
            end1 = i + 1
            end2 = end1 + numBay + 1
            for j in range(numFloor):

                if eleType == "elasticBeam":
                    ops.element('elasticBeamColumn', eleTag, end1, end2, A, E,
                                I, 1, '-mass', M, massType)
                elif eleType == "forceBeamElasticSection":
                    ops.element('forceBeamColumn', eleTag, end1, end2,
                                transfTag, integTag1, '-mass', M)
                elif eleType == "dispBeamElasticSection":
                    ops.element('dispBeamColumn', eleTag, end1, end2,
                                transfTag, integTag1, '-mass', M, massType)
                elif eleType == "forceBeamFiberSectionElasticMaterial":
                    ops.element('forceBeamColumn', eleTag, end1, end2,
                                transfTag, integTag2, '-mass', M)
                elif eleType == "dispBeamFiberSectionElasticMaterial":
                    ops.element('dispBeamColumn', eleTag, end1, end2,
                                transfTag, integTag2, '-mass', M, massType)
                else:
                    print("BARF")

                end1 = end2
                end2 = end1 + numBay + 1
                eleTag += 1

        # add beam elements
        for j in range(1, numFloor + 1):
            end1 = (numBay + 1) * j + 1
            end2 = end1 + 1
            for i in range(numBay):
                if eleType == "elasticBeam":
                    ops.element('elasticBeamColumn', eleTag, end1, end2, A, E,
                                I, 1, '-mass', M, massType)
                elif eleType == "forceBeamElasticSection":
                    ops.element('forceBeamColumn', eleTag, end1, end2,
                                transfTag, integTag1, '-mass', M)
                elif eleType == "dispBeamElasticSection":
                    ops.element('dispBeamColumn', eleTag, end1, end2,
                                transfTag, integTag1, '-mass', M, massType)
                elif eleType == "forceBeamFiberSectionElasticMaterial":
                    ops.element('forceBeamColumn', eleTag, end1, end2,
                                transfTag, integTag2, '-mass', M)
                elif eleType == "dispBeamFiberSectionElasticMaterial":
                    ops.element('dispBeamColumn', eleTag, end1, end2,
                                transfTag, integTag2, '-mass', M, massType)
                else:
                    print("BARF")

    #           element(elasticBeamColumn eleTag end1 end2 A E I 1 -mass M
                end1 = end2
                end2 = end1 + 1
                eleTag += 1

        # calculate eigenvalues
        numEigen = 3
        eigenValues = ops.eigen(numEigen)
        PI = 2 * asin(1.0)

        # determine PASS/FAILURE of test
        testOK = 0

        # print table of camparsion
        #                         Bathe & Wilson               Peterson                    SAP2000                  SeismoStruct

        comparisonResults = [[0.589541, 5.52695, 16.5878],
                             [0.589541, 5.52696, 16.5879],
                             [0.589541, 5.52696, 16.5879],
                             [0.58955, 5.527, 16.588]]
        print("\n\nEigenvalue Comparisons for eleType:", eleType)
        tolerances = [9.99e-7, 9.99e-6, 9.99e-5]
        formatString = '{:>15}{:>15}{:>15}{:>15}{:>15}'
        print(
            formatString.format('OpenSees', 'Bathe&Wilson', 'Peterson',
                                'SAP2000', 'SeismoStruct'))
        formatString = '{:>15.5f}{:>15.4f}{:>15.4f}{:>15.4f}{:>15.3f}'
        for i in range(numEigen):
            lamb = eigenValues[i]
            print(
                formatString.format(lamb, comparisonResults[0][i],
                                    comparisonResults[1][i],
                                    comparisonResults[2][i],
                                    comparisonResults[3][i]))
            resultOther = comparisonResults[2][i]
            tol = tolerances[i]
            if abs(lamb - resultOther) > tol:
                testOK = -1
                print("failed->", abs(lamb - resultOther), tol)

        assert testOK == 0

    solverTypes = [
        '-genBandArpack', '-fullGenLapack', '-UmfPack', '-SuperLU',
        '-ProfileSPD'
    ]

    for solverType in solverTypes:

        eleType = 'elasticBeam'

        ops.wipe()

        ops.model('Basic', '-ndm', 2)

        #    units kip, ft

        # properties
        bayWidth = 20.0
        storyHeight = 10.0

        numBay = 10
        numFloor = 9

        A = 3.0  #area = 3ft^2
        E = 432000.0  #youngs mod = 432000 k/ft^2
        I = 1.0  #second moment of area I=1ft^4
        M = 3.0  #mas/length = 4 kip sec^2/ft^2
        coordTransf = "Linear"  # Linear, PDelta, Corotational
        massType = "-lMass"  # -lMass, -cMass

        nPts = 3  # numGauss Points

        # an elastic material
        ops.uniaxialMaterial('Elastic', 1, E)

        # an elastic section
        ops.section('Elastic', 1, E, A, I)

        # a fiber section with A=3 and I = 1 (b=1.5, d=2) 2d bending about y-y axis
        #   b 1.5 d 2.0
        y = 2.0
        z = 1.5
        numFiberY = 2000  # note we only need so many to get the required accuracy on eigenvalue 1e-7!
        numFiberZ = 1
        ops.section('Fiber', 2)
        #   patch rect 1 numFiberY numFiberZ 0.0 0.0 z y
        ops.patch('quad', 1, numFiberY, numFiberZ, -y / 2.0, -z / 2.0, y / 2.0,
                  -z / 2.0, y / 2.0, z / 2.0, -y / 2.0, z / 2.0)

        # add the nodes
        #  - floor at a time
        nodeTag = 1
        yLoc = 0.
        for j in range(0, numFloor + 1):
            xLoc = 0.
            for i in range(numBay + 1):
                ops.node(nodeTag, xLoc, yLoc)
                xLoc += bayWidth
                nodeTag += 1

            yLoc += storyHeight

        # fix base nodes
        for i in range(1, numBay + 2):
            ops.fix(i, 1, 1, 1)

        # add column element
        transfTag = 1
        ops.geomTransf(coordTransf, transfTag)
        integTag1 = 1
        ops.beamIntegration('Lobatto', integTag1, 1, nPts)
        integTag2 = 2
        ops.beamIntegration('Lobatto', integTag2, 2, nPts)
        eleTag = 1
        for i in range(numBay + 1):
            end1 = i + 1
            end2 = end1 + numBay + 1
            for j in range(numFloor):

                if eleType == "elasticBeam":
                    ops.element('elasticBeamColumn', eleTag, end1, end2, A, E,
                                I, 1, '-mass', M, massType)

                elif eleType == "forceBeamElasticSection":
                    ops.element('forceBeamColumn', eleTag, end1, end2,
                                transfTag, integTag1, '-mass', M)

                elif eleType == "dispBeamElasticSection":
                    ops.element('dispBeamColumn', eleTag, end1, end2,
                                transfTag, integTag1, '-mass', M, massType)
                elif eleType == "forceBeamFiberSectionElasticMaterial":
                    ops.element('forceBeamColumn', eleTag, end1, end2,
                                transfTag, integTag2, '-mass', M)

                elif eleType == "dispBeamFiberSectionElasticMaterial":
                    ops.element('dispBeamColumn', eleTag, end1, end2,
                                transfTag, integTag2, '-mass', M, massType)
                else:
                    print("BARF")

                end1 = end2
                end2 = end1 + numBay + 1
                eleTag += 1

        # add beam elements
        for j in range(1, numFloor + 1):
            end1 = (numBay + 1) * j + 1
            end2 = end1 + 1
            for i in range(numBay):
                if eleType == "elasticBeam":
                    ops.element('elasticBeamColumn', eleTag, end1, end2, A, E,
                                I, 1, '-mass', M, massType)
                elif eleType == "forceBeamElasticSection":
                    ops.element('forceBeamColumn', eleTag, end1, end2,
                                transfTag, integTag1, '-mass', M)
                elif eleType == "dispBeamElasticSection":
                    ops.element('dispBeamColumn', eleTag, end1, end2,
                                transfTag, integTag1, '-mass', M, massType)
                elif eleType == "forceBeamFiberSectionElasticMaterial":
                    ops.element('forceBeamColumn', eleTag, end1, end2,
                                transfTag, integTag2, '-mass', M)
                elif eleType == "dispBeamFiberSectionElasticMaterial":
                    ops.element('dispBeamColumn', eleTag, end1, end2,
                                transfTag, integTag2, '-mass', M, massType)
                else:
                    print("BARF")

    #           element(elasticBeamColumn eleTag end1 end2 A E I 1 -mass M
                end1 = end2
                end2 = end1 + 1
                eleTag += 1

        # calculate eigenvalues
        numEigen = 3
        eigenValues = ops.eigen(solverType, numEigen)
        PI = 2 * asin(1.0)

        # determine PASS/FAILURE of test
        testOK = 0

        # print table of camparsion
        #                         Bathe & Wilson               Peterson                    SAP2000                  SeismoStruct

        comparisonResults = [[0.589541, 5.52695, 16.5878],
                             [0.589541, 5.52696, 16.5879],
                             [0.589541, 5.52696, 16.5879],
                             [0.58955, 5.527, 16.588]]
        print("\n\nEigenvalue Comparisons for solverType:", solverType)
        tolerances = [9.99e-7, 9.99e-6, 9.99e-5]
        formatString = '{:>15}{:>15}{:>15}{:>15}{:>15}'
        print(
            formatString.format('OpenSees', 'Bathe&Wilson', 'Peterson',
                                'SAP2000', 'SeismoStruct'))
        formatString = '{:>15.5f}{:>15.4f}{:>15.4f}{:>15.4f}{:>15.3f}'
        for i in range(numEigen):
            lamb = eigenValues[i]
            print(
                formatString.format(lamb, comparisonResults[0][i],
                                    comparisonResults[1][i],
                                    comparisonResults[2][i],
                                    comparisonResults[3][i]))
            resultOther = comparisonResults[2][i]
            tol = tolerances[i]
            if abs(lamb - resultOther) > tol:
                testOK = -1
                print("failed->", abs(lamb - resultOther), tol)

        assert testOK == 0
Exemple #18
0
def get_inelastic_response(mass,
                           k_spring,
                           f_yield,
                           motion,
                           dt,
                           xi=0.05,
                           r_post=0.0):
    """
    Run seismic analysis of a nonlinear SDOF

    :param mass: SDOF mass
    :param k_spring: spring stiffness
    :param f_yield: yield strength
    :param motion: list, acceleration values
    :param dt: float, time step of acceleration values
    :param xi: damping ratio
    :param r_post: post-yield stiffness
    :return:
    """

    opy.wipe()
    opy.model('basic', '-ndm', 2, '-ndf', 3)  # 2 dimensions, 3 dof per node

    # Establish nodes
    bot_node = 1
    top_node = 2
    opy.node(bot_node, 0., 0.)
    opy.node(top_node, 0., 0.)

    # Fix bottom node
    opy.fix(top_node, opc.FREE, opc.FIXED, opc.FIXED)
    opy.fix(bot_node, opc.FIXED, opc.FIXED, opc.FIXED)
    # Set out-of-plane DOFs to be slaved
    opy.equalDOF(1, 2, *[2, 3])

    # nodal mass (weight / g):
    opy.mass(top_node, mass, 0., 0.)

    # Define material
    bilinear_mat_tag = 1
    mat_type = "Steel01"
    mat_props = [f_yield, k_spring, r_post]
    opy.uniaxialMaterial(mat_type, bilinear_mat_tag, *mat_props)

    # Assign zero length element
    beam_tag = 1
    opy.element('zeroLength', beam_tag, bot_node, top_node, "-mat",
                bilinear_mat_tag, "-dir", 1, '-doRayleigh', 1)

    # Define the dynamic analysis
    load_tag_dynamic = 1
    pattern_tag_dynamic = 1

    values = list(-1 * motion)  # should be negative
    opy.timeSeries('Path', load_tag_dynamic, '-dt', dt, '-values', *values)
    opy.pattern('UniformExcitation', pattern_tag_dynamic, opc.X, '-accel',
                load_tag_dynamic)

    # set damping based on first eigen mode
    angular_freq2 = opy.eigen('-fullGenLapack', 1)
    if hasattr(angular_freq2, '__len__'):
        angular_freq2 = angular_freq2[0]
    angular_freq = angular_freq2**0.5
    alpha_m = 0.0
    beta_k = 2 * xi / angular_freq
    beta_k_comm = 0.0
    beta_k_init = 0.0

    opy.rayleigh(alpha_m, beta_k, beta_k_init, beta_k_comm)

    # Run the dynamic analysis

    opy.wipeAnalysis()

    opy.algorithm('Newton')
    opy.system('SparseGeneral')
    opy.numberer('RCM')
    opy.constraints('Transformation')
    opy.integrator('Newmark', 0.5, 0.25)
    opy.analysis('Transient')

    tol = 1.0e-10
    iterations = 10
    opy.test('EnergyIncr', tol, iterations, 0, 2)
    analysis_time = (len(values) - 1) * dt
    analysis_dt = 0.001
    outputs = {
        "time": [],
        "rel_disp": [],
        "rel_accel": [],
        "rel_vel": [],
        "force": []
    }

    while opy.getTime() < analysis_time:
        curr_time = opy.getTime()
        opy.analyze(1, analysis_dt)
        outputs["time"].append(curr_time)
        outputs["rel_disp"].append(opy.nodeDisp(top_node, 1))
        outputs["rel_vel"].append(opy.nodeVel(top_node, 1))
        outputs["rel_accel"].append(opy.nodeAccel(top_node, 1))
        opy.reactions()
        outputs["force"].append(
            -opy.nodeReaction(bot_node, 1))  # Negative since diff node
    opy.wipe()
    for item in outputs:
        outputs[item] = np.array(outputs[item])

    return outputs
#    row= 0
#    
#    gravity_load_data[:,0]= node_data[wall.shape[0]:node_data.shape[0],0]
#    
#    for story in range(num_story):
#        gravity_load_data[row:row+ wall.shape[0],3]= -1*np.multiply(wall_data_arr[:,18],wall_data_arr[:,19])*original_bldg.iat[bldg_num,38]**2*0.0254**2*(1200+bldg.iat[bldg_num,8]*conc_mat[4]*9.81)
#        
#        row= row+ wall.shape[0]
#    for i in range(gravity_load_data.shape[0]):
#        ops.load(int(gravity_load_data[i,0]), gravity_load_data[i,1], gravity_load_data[i,2], gravity_load_data[i,3], gravity_load_data[i,4], gravity_load_data[i,5], gravity_load_data[i,6])

    # =============================================================================
    #       Analysis Generation
    # =============================================================================
    #eigen command
    eigen_values= ops.eigen(num_eigen)
    
    period= 2*math.pi/np.sqrt(eigen_values)
    
    period_data[bldg_num,:]= period
    
    # render the model after defining all the nodes and elements
    #plot_model()
            
    ops.wipe()

#plot period vs. story
plt.plot(period_data[:,0], bldg_arr[:,3], 'o', color='black',markersize=5)
plt.ylim(0, 35)
plt.xlim(0, 6)
plt.xlabel('Fundamental period (s)')
Exemple #20
0
def test_EigenAnal_twoStoryFrame1():
    ops.wipe()

    #input
    m = 100.0 / 386.0
    numModes = 2

    #material
    A = 63.41
    I = 320.0
    E = 29000.0

    #geometry
    L = 240.
    h = 120.

    # define the model
    #---------------------------------
    #model builder
    ops.model('BasicBuilder', '-ndm', 2, '-ndf', 3)

    # nodal coordinates:
    ops.node(1, 0., 0.)
    ops.node(2, L, 0.)
    ops.node(3, 0., h)
    ops.node(4, L, h)
    ops.node(5, 0., 2 * h)
    ops.node(6, L, 2 * h)

    # Single point constraints -- Boundary Conditions
    ops.fix(1, 1, 1, 1)
    ops.fix(2, 1, 1, 1)

    # assign mass
    ops.mass(3, m, 0., 0.)
    ops.mass(4, m, 0., 0.)
    ops.mass(5, m / 2., 0., 0.)
    ops.mass(6, m / 2., 0., 0.)

    # define geometric transformation:
    TransfTag = 1
    ops.geomTransf('Linear', TransfTag)

    # define elements:
    # columns
    ops.element('elasticBeamColumn', 1, 1, 3, A, E, 2. * I, TransfTag)
    ops.element('elasticBeamColumn', 2, 3, 5, A, E, I, TransfTag)
    ops.element('elasticBeamColumn', 3, 2, 4, A, E, 2. * I, TransfTag)
    ops.element('elasticBeamColumn', 4, 4, 6, A, E, I, TransfTag)
    # beams
    ops.element('elasticBeamColumn', 5, 3, 4, A, E, 2 * I, TransfTag)
    ops.element('elasticBeamColumn', 6, 5, 6, A, E, I, TransfTag)

    # record eigenvectors
    #----------------------
    # for { k 1 } { k <= numModes } { incr k } {
    #     recorder Node -file format "modes/mode%i.out" k -nodeRange 1 6 -dof 1 2 3  "eigen k"
    # }

    # perform eigen analysis
    #-----------------------------
    lamb = ops.eigen(numModes)

    # calculate frequencies and periods of the structure
    #---------------------------------------------------
    omega = []
    f = []
    T = []
    pi = 3.141593

    for lam in lamb:
        print("labmbda = ", lam)
        omega.append(math.sqrt(lam))
        f.append(math.sqrt(lam) / (2 * pi))
        T.append((2 * pi) / math.sqrt(lam))

    print("periods are ", T)

    # write the output file cosisting of periods
    #--------------------------------------------
    period = "Periods.txt"
    Periods = open(period, "w")
    for t in T:
        Periods.write(repr(t) + '\n')

    Periods.close()

    # create display  for mode shapes
    #---------------------------------
    #                 windowTitle xLoc yLoc xPixels yPixels
    # recorder display "Mode Shape 1"  10    10     500      500     -wipe
    # prp h h 1                                         # projection reference point (prp) defines the center of projection (viewer eye)
    # vup  0  1 0                                         # view-up vector (vup)
    # vpn  0  0 1                                         # view-plane normal (vpn)
    # viewWindow -200 200 -200 200                        # coordiantes of the window relative to prp
    # display -1 5 20
    # the 1st arg. is the tag for display mode (ex. -1 is for the first mode shape)
    # the 2nd arg. is magnification factor for nodes, the 3rd arg. is magnif. factor of deformed shape
    # recorder display "Mode Shape 2" 10 510 500 500 -wipe
    # prp h h 1
    # vup  0  1 0
    # vpn  0  0 1
    # viewWindow -200 200 -200 200
    # display -2 5 20

    # Run a one step gravity load with no loading (to record eigenvectors)
    #-----------------------------------------------------------------------
    ops.integrator('LoadControl', 0.0, 1, 0.0, 0.0)

    # Convergence test
    #                     tolerance maxIter displayCode
    ops.test('EnergyIncr', 1.0e-10, 100, 0)

    # Solution algorithm
    ops.algorithm('Newton')

    # DOF numberer
    ops.numberer('RCM')

    # Constraint handler
    ops.constraints('Transformation')

    # System of equations solver
    ops.system('ProfileSPD')

    ops.analysis('Static')
    res = ops.analyze(1)
    if res < 0:
        print("Modal analysis failed")

    # get values of eigenvectors for translational DOFs
    #---------------------------------------------------
    f11 = ops.nodeEigenvector(3, 1, 1)
    f21 = ops.nodeEigenvector(5, 1, 1)
    f12 = ops.nodeEigenvector(3, 2, 1)
    f22 = ops.nodeEigenvector(5, 2, 1)
    print("eigenvector 1: ", [f11 / f21, f21 / f21])
    print("eigenvector 2: ", [f12 / f22, f22 / f22])

    assert abs(T[0] - 0.628538768190688) < 1e-12 and abs(
        T[1] - 0.2359388635361575) < 1e-12 and abs(
            f11 / f21 - 0.3869004256389493) < 1e-12 and abs(
                f21 / f21 - 1.0) < 1e-12 and abs(f12 / f22 + 1.2923221761110006
                                                 ) < 1e-12 and abs(f22 / f22 -
                                                                   1.0) < 1e-12
def get_inelastic_response(fb, asig, extra_time=0.0, xi=0.05, analysis_dt=0.001):
    """
    Run seismic analysis of a nonlinear FrameBuilding

    :param fb: FrameBuilding object
    :param asig: AccSignal object
    :param extra_time: float, additional analysis time after end of ground motion
    :param xi: damping ratio
    :param analysis_dt: time step to perform the analysis
    :return:
    """

    op.wipe()
    op.model('basic', '-ndm', 2, '-ndf', 3)  # 2 dimensions, 3 dof per node

    q_floor = 10000.  # kPa
    trib_width = fb.floor_length
    trib_mass_per_length = q_floor * trib_width / 9.8

    # Establish nodes and set mass based on trib area
    # Nodes named as: C<column-number>-S<storey-number>, first column starts at C1-S0 = ground level left
    nd = OrderedDict()
    col_xs = np.cumsum(fb.bay_lengths)
    col_xs = np.insert(col_xs, 0, 0)
    n_cols = len(col_xs)
    sto_ys = fb.heights
    sto_ys = np.insert(sto_ys, 0, 0)
    for cc in range(1, n_cols + 1):
        for ss in range(fb.n_storeys + 1):
            n_i = cc * 100 + ss
            nd["C%i-S%i" % (cc, ss)] = n_i
            op.node(n_i, col_xs[cc - 1], sto_ys[ss])

            if ss != 0:
                if cc == 1:
                    node_mass = trib_mass_per_length * fb.bay_lengths[0] / 2
                elif cc == n_cols:
                    node_mass = trib_mass_per_length * fb.bay_lengths[-1] / 2
                else:
                    node_mass = trib_mass_per_length * (fb.bay_lengths[cc - 2] + fb.bay_lengths[cc - 1] / 2)
                op.mass(n_i, node_mass)

    # Set all nodes on a storey to have the same displacement
    for ss in range(0, fb.n_storeys + 1):
        for cc in range(1, n_cols + 1):
            op.equalDOF(nd["C%i-S%i" % (1, ss)], nd["C%i-S%i" % (cc, ss)],  opc.X)

    # Fix all base nodes
    for cc in range(1, n_cols + 1):
        op.fix(nd["C%i-S%i" % (cc, 0)], opc.FIXED, opc.FIXED, opc.FIXED)

    # Coordinate transformation
    geo_tag = 1
    trans_args = []
    op.geomTransf("Linear", geo_tag, *[])

    l_hinge = fb.bay_lengths[0] * 0.1

    # Define material
    e_conc = 30.0e6
    i_beams = 0.4 * fb.beam_widths * fb.beam_depths ** 3 / 12
    i_columns = 0.5 * fb.column_widths * fb.column_depths ** 3 / 12
    a_beams = fb.beam_widths * fb.beam_depths
    a_columns = fb.column_widths * fb.column_depths
    ei_beams = e_conc * i_beams
    ei_columns = e_conc * i_columns
    eps_yield = 300.0e6 / 200e9
    phi_y_col = calc_yield_curvature(fb.column_depths, eps_yield)
    phi_y_beam = calc_yield_curvature(fb.beam_depths, eps_yield)

    # Define beams and columns

    md = OrderedDict()  # material dict
    sd = OrderedDict()  # section dict
    ed = OrderedDict()  # element dict
    # Columns named as: C<column-number>-S<storey-number>, first column starts at C1-S0 = ground floor left
    # Beams named as: B<bay-number>-S<storey-number>, first beam starts at B1-S1 = first storey left (foundation at S0)
    for ss in range(fb.n_storeys):

        # set columns
        for cc in range(1, fb.n_cols + 1):
            ele_i = cc * 100 + ss
            md["C%i-S%i" % (cc, ss)] = ele_i
            sd["C%i-S%i" % (cc, ss)] = ele_i
            ed["C%i-S%i" % (cc, ss)] = ele_i
            mat_props = elastic_bilin(ei_columns[ss][cc - 1], 0.05 * ei_columns[ss][cc - 1], phi_y_col[ss][cc - 1])
            #print(opc.ELASTIC_BILIN, ele_i, *mat_props)
            op.uniaxialMaterial(opc.ELASTIC_BILIN, ele_i, *mat_props)
            # op.uniaxialMaterial("Elastic", ele_i, ei_columns[ss][cc - 1])

            node_numbers = [nd["C%i-S%i" % (cc, ss)], nd["C%i-S%i" % (cc, ss + 1)]]
            op.element(opc.ELASTIC_BEAM_COLUMN, ele_i,
                       *node_numbers,
                       a_columns[ss - 1][cc - 1],
                       e_conc,
                       i_columns[ss - 1][cc - 1],
                       geo_tag
                       )

        # Set beams
        for bb in range(1, fb.n_bays + 1):
            ele_i = bb * 10000 + ss
            md["B%i-S%i" % (bb, ss)] = ele_i
            sd["B%i-S%i" % (bb, ss)] = ele_i
            ed["B%i-S%i" % (bb, ss)] = ele_i
            mat_props = elastic_bilin(ei_beams[ss][bb - 1], 0.05 * ei_beams[ss][bb - 1], phi_y_beam[ss][bb - 1])
            op.uniaxialMaterial(opc.ELASTIC_BILIN, ele_i, *mat_props)
            # op.uniaxialMaterial("Elastic", ele_i, ei_beams[ss][bb - 1])
            node_numbers = [nd["C%i-S%i" % (bb, ss + 1)], nd["C%i-S%i" % (bb + 1, ss + 1)]]
            print((opc.BEAM_WITH_HINGES, ele_i,
                       *node_numbers,
                        sd["B%i-S%i" % (bb, ss)], l_hinge,
                       sd["B%i-S%i" % (bb, ss)], l_hinge,
                       sd["B%i-S%i" % (bb, ss)], geo_tag
                       ))
            # Old definition
            # op.element(opc.BEAM_WITH_HINGES, ele_i,
            #  *[nd["C%i-S%i" % (bb, ss - 1)], nd["C%i-S%i" % (bb + 1, ss)]],
            #  sd["B%i-S%i" % (bb, ss)], l_hinge,
            #  sd["B%i-S%i" % (bb, ss)], l_hinge,
            #  e_conc,
            #  a_beams[ss - 1][bb - 1],
            #  i_beams[ss - 1][bb - 1], geo_tag
            #  )
            # New definition
            # op.element(opc.BEAM_WITH_HINGES, ele_i,
            #            *node_numbers,
            #             sd["B%i-S%i" % (bb, ss)], l_hinge,
            #            sd["B%i-S%i" % (bb, ss)], l_hinge,
            #            sd["B%i-S%i" % (bb, ss)], geo_tag  # TODO: make this elastic
            #
            #            )

            # Elastic definition
            op.element(opc.ELASTIC_BEAM_COLUMN, ele_i,
                       *node_numbers,
                       a_beams[ss - 1][bb - 1],
                       e_conc,
                       i_beams[ss - 1][bb - 1],
                       geo_tag
                       )

    # Define the dynamic analysis
    load_tag_dynamic = 1
    pattern_tag_dynamic = 1

    values = list(-1 * asig.values)  # should be negative
    op.timeSeries('Path', load_tag_dynamic, '-dt', asig.dt, '-values', *values)
    op.pattern('UniformExcitation', pattern_tag_dynamic, opc.X, '-accel', load_tag_dynamic)

    # set damping based on first eigen mode
    angular_freq2 = op.eigen('-fullGenLapack', 1)
    if hasattr(angular_freq2, '__len__'):
        angular_freq2 = angular_freq2[0]
    angular_freq = angular_freq2 ** 0.5
    if isinstance(angular_freq, complex):
        raise ValueError("Angular frequency is complex, issue with stiffness or mass")
    alpha_m = 0.0
    beta_k = 2 * xi / angular_freq
    beta_k_comm = 0.0
    beta_k_init = 0.0
    period = angular_freq / 2 / np.pi
    print("period: ", period)

    op.rayleigh(alpha_m, beta_k, beta_k_init, beta_k_comm)

    # Run the dynamic analysis

    op.wipeAnalysis()

    op.algorithm('Newton')
    op.system('SparseGeneral')
    op.numberer('RCM')
    op.constraints('Transformation')
    op.integrator('Newmark', 0.5, 0.25)
    op.analysis('Transient')
    #op.test("NormDispIncr", 1.0e-1, 2, 0)
    tol = 1.0e-10
    iter = 10
    op.test('EnergyIncr', tol, iter, 0, 2)  # TODO: make this test work
    analysis_time = (len(values) - 1) * asig.dt + extra_time
    outputs = {
        "time": [],
        "rel_disp": [],
        "rel_accel": [],
        "rel_vel": [],
        "force": []
    }
    print("Analysis starting")
    while op.getTime() < analysis_time:
        curr_time = op.getTime()
        op.analyze(1, analysis_dt)
        outputs["time"].append(curr_time)
        outputs["rel_disp"].append(op.nodeDisp(nd["C%i-S%i" % (1, fb.n_storeys)], opc.X))
        outputs["rel_vel"].append(op.nodeVel(nd["C%i-S%i" % (1, fb.n_storeys)], opc.X))
        outputs["rel_accel"].append(op.nodeAccel(nd["C%i-S%i" % (1, fb.n_storeys)], opc.X))
        op.reactions()
        react = 0
        for cc in range(1, fb.n_cols):
            react += -op.nodeReaction(nd["C%i-S%i" % (cc, 0)], opc.X)
        outputs["force"].append(react)  # Should be negative since diff node
    op.wipe()
    for item in outputs:
        outputs[item] = np.array(outputs[item])

    return outputs
Exemple #22
0
rho = 2400 * kg / m**3
nu = 0.20  # Poisson's ratio of soil
E = 2460000 * N / cm**2
ops.nDMaterial('ElasticIsotropic', mTg, E, nu, rho)

# espesor de los elementos
B = 0.25 * m

# construccion de nodos
for i in range(nNode):
    ops.node(i + 1, *Node[i][1:])

# construccion de elementos
for i in range(nEle):
    if (Ele[i][0] == 1):
        ops.element('quad', i + 1, *Ele[i][2:], B, 'PlaneStress', Ele[i][0])

# condiciones de frontera
boundFix(nNode, Node)

# calculo de los modos de vibracion
Nmodes = 6
Tmodes = ops.eigen(Nmodes)
for i in range(Nmodes):
    Tmodes[i] = 2 * math.pi / Tmodes[i]**0.5
print(Tmodes)

# Grafico de la deformada
fig = plt.figure(figsize=(10, 10))
opsv.plot_mode_shape(4, sfac=10)
plt.show()