Пример #1
0
    def ops_cyclic():
        ops.remove('recorders')
        ops.wipeAnalysis()
        ops.loadConst('-time', 0.0)

        # set hysteresis
        ops.recorder('Node', '-file', f'output\\cyclic_81_disp_{argv[0]}.out',
                     '-time', '-node', 81, '-dof', 1, 'disp')
        ops.recorder('Node', '-file', f'output\\cyclic_81_rea_{argv[0]}.out',
                     '-time', '-nodeRange', 1, 8, '-dof', 1, 'reaction')
        # ops.timeSeries("Path", 2, '-dt', 0.1, '-filePath', 'disp.txt')
        ops.timeSeries('Linear', 2)
        ops.pattern('Plain', 2, 2)
        # ops.sp(81, 1, 1)
        ops.load(81, 1, 0, 0, 0, 0, 0)
        # ops.constraints('Penalty', 1e20, 1e20)
        # ops.numberer('RCM')
        # ops.system('BandGeneral')
        # ops.test('NormDispIncr', 1e-4, 1e6, 2)
        # ops.algorithm('KrylovNewton')
        # ops.integrator('LoadControl', 0.1)
        # ops.analysis('Static')
        # # ops.analyze(12961)
        # with open('disp.txt', 'r') as f:
        #     i = 1
        #     lines = f.readlines()
        #     count = len(lines)
        #     for line in lines:
        #         logger.info(
        #             'position = {} line = {} and {:3%}'.format(line[:-1], i, i/count))
        #         ops.analyze(1)
        #         i = i + 1
        CyclicDisplace(1e-3, 80, 1e-3, 81, 1, 1e-6, 1e6)
Пример #2
0
def run(arg_1, arg_2, arg_3, arg_4):
    ops.reset()
    ops.wipe()

    ops.model('basic', '-ndm', 3, '-ndf', 6)

    ops.node(1, 0.0, 0.0, 0.0)
    ops.node(2, 0.0, 3.2, 0.0)
    ops.fix(1, 1, 1, 1, 1, 1, 1)

    ops.uniaxialMaterial('Concrete01', 1, -80.0e6, -0.002, 0.0, -0.005)

    ops.section('Fiber', 1, '-GJ', 1)
    ops.patch('rect', 1, 10, 10, -0.8, -0.1, 0.8, 0.1)

    ops.geomTransf('Linear', 1, 0, 0, 1)
    ops.beamIntegration('Legendre', 1, 1, 10)
    ops.element('dispBeamColumn', 1, 1, 2, 1, 1)

    ops.timeSeries('Linear', 1)
    ops.pattern('Plain', 1, 1)
    ops.load(2, 0, -24586.24, 0, 0, 0, 0)

    ops.constraints('Plain')
    ops.numberer('RCM')
    ops.system('UmfPack')
    ops.test('NormDispIncr', 1.0e-6, 2000)
    ops.algorithm('Newton')
    ops.integrator('LoadControl', 0.01)
    ops.analysis('Static')
    ops.analyze(100)

    ops.wipeAnalysis()
    ops.loadConst('-time', 0.0)

    ops.recorder('Node', '-file', 'disp.out', ' -time',
                 '-node',  2, '-dof', 1, 'disp')
    ops.recorder('Node', '-file', 'react.out', '-time ',
                 '-node', 2, '-dof', 1, 'reaction')

    ops.timeSeries('Linear', 2)
    ops.pattern('Plain', 2, 2)
    ops.load(2, 11500, 0, 0, 0, 0, 0)
    ops.constraints('Plain')
    ops.numberer('RCM')
    ops.system('UmfPack')
    ops.test('NormDispIncr', 1.0, 2000)
    ops.algorithm('Newton')
    ops.integrator('LoadControl',  0.01)
    ops.analysis('Static')
    # ops.analyze(100)

    step = 100
    data = np.zeros((step, 2))
    for i in range(step):
        ops.analyze(1)
        data[i, 0] = ops.nodeDisp(2, 1)
        data[i, 1] = ops.getLoadFactor(2) * 11500
    return data
Пример #3
0
def ops_cyclic():
    ops.remove('recorders')
    ops.wipeAnalysis()
    ops.loadConst('-time', 0.0)

    # set hysteresis
    ops.recorder('Node', '-file', 'output\\cyclic_657.out',
                 '-time', '-node', 651, '-dof', 1, 'disp')
    ops.pattern('Plain', 2, 1)
    ops.load(651, 1, 0, 0, 0, 0, 0)
    CyclicDisplace(1e-3, 80, 1e-3, 651, 1, 1, 1e6)
Пример #4
0
def perform_modal_analysis_and_comparison(etabs_periods):
    eigenValues = modal_response(len(etabs_periods))
    periods = 2 * math.pi / np.sqrt(eigenValues)

    # compare modal analysis results
    print('\nETABS Periods: ')
    print(etabs_periods)
    print('\nOpenSees Periods: ')
    print([round(n, 3) for n in list(periods)])
    print('\nAgreement: (ETABS Periods/OpenSees Periods)')
    print(etabs_periods / periods)
    op.wipeAnalysis()
    return
def run_gravity_analysis(steps=10):
    """
    Run gravity analysis (in 10 steps)
    """
    ops.wipeAnalysis()
    ops.system("BandGeneral")
    ops.numberer("RCM")
    ops.constraints("Transformation")
    ops.test("NormDispIncr", 1.0E-12, 10, 3)
    ops.algorithm("Newton")  # KrylovNewton
    ops.integrator("LoadControl", 1 / steps)
    ops.analysis("Static")
    ops.analyze(steps)
    title("Gravity Analysis Completed!")
    # Set the gravity loads to be constant & reset the time in the domain
    ops.loadConst("-time", 0.0)
    ops.wipeAnalysis()
Пример #6
0
def run_sensitivity_analysis(ctrlNode,
                             dof,
                             baseNode,
                             SensParam,
                             steps=500,
                             IOflag=False):
    """
    Run load-control sensitivity analysis
    """
    ops.wipeAnalysis()
    start_time = time.time()

    title("Running Load-Control Sensitivity Analysis ...")

    ops.system("BandGeneral")
    ops.numberer("RCM")
    ops.constraints("Transformation")
    ops.test("NormDispIncr", 1.0E-12, 10, 3)
    ops.algorithm("Newton")  # KrylovNewton
    ops.integrator("LoadControl", 1 / steps)
    ops.analysis("Static")
    ops.sensitivityAlgorithm(
        "-computeAtEachStep"
    )  # automatically compute sensitivity at the end of each step

    outputs = {
        "time": np.array([]),
        "disp": np.array([]),
        "force": np.array([]),
    }

    for sens in SensParam:
        outputs[f"sensDisp_{sens}"] = np.array([]),

    for i in range(steps):
        ops.reactions()
        if IOflag:
            print(
                f"Single Cycle Response: Step #{i}, Node #{ctrlNode}: {ops.nodeDisp(ctrlNode, dof):.3f} {LunitTXT} / {-ops.nodeReaction(baseNode, dof):.2f} {FunitTXT}."
            )
        ops.analyze(1)
        tCurrent = ops.getTime()

        outputs["time"] = np.append(outputs["time"], tCurrent)
        outputs["disp"] = np.append(outputs["disp"],
                                    ops.nodeDisp(ctrlNode, dof))
        outputs["force"] = np.append(outputs["force"],
                                     -ops.nodeReaction(baseNode, dof))

        for sens in SensParam:
            # sensDisp(patternTag, paramTag)
            outputs[f"sensDisp_{sens}"] = np.append(
                outputs[f"sensDisp_{sens}"],
                ops.sensNodeDisp(ctrlNode, dof, sens))

    title("Sensitvity Analysis Completed!")
    print(
        f"Analysis elapsed time is {(time.time() - start_time):.3f} seconds.\n"
    )

    return outputs
Пример #7
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
Пример #8
0
def run_analysis(GM_dt, GM_npts, TS_List, EDP_specs, model_params):
    """
    Run dynamic analysis for a time history and return a dictionary of envelope EDPs.

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

    Parameters
    ----------
    GM_dt: float
        Time step of time series
    GM_npts: float
        Number of points in time series
    TS_List: float
        1x2 list where first component is a list of accelerations in the X
        direction, the second component is a list of accelerations in the Y
        direction.
    EDP_specs: dict

    """

    stories = model_params["NumberOfStories"]
    node_tags = list(range(stories + 1))
    height = ops.nodeCoord(node_tags[-1], 3) - ops.nodeCoord(node_tags[0], 3)

    # define parameters for dynamic analysis
    dt = GM_dt  # time increment for analysis

    GMX = TS_List[0]  # list of GM accelerations in X direction
    GMY = TS_List[1]  # list of GM accelerations in Y direction

    driftLimit = 0.20  # interstory drift limit indicating collapse
    tol = 1.e-08  # tolerance criteria to check for convergence
    maxiter = 30  # max number of iterations to check
    subSteps = 2  # number of subdivisions in cases of ill convergence

    # pad shorter record with zeros (free vibration) such that two horizontal records are the same length
    nsteps = max(len(GMX), len(GMY))
    for GM in [GMX, GMY]:
        if len(GM) < nsteps:
            diff = nsteps - len(GM)
            GM.extend(np.zeros(diff))

    # initialize dictionary of envelope EDPs
    envelopeDict = {}
    for edp in EDP_specs:
        envelopeDict[edp] = {}
        for loc in EDP_specs[edp]:
            envelopeDict[edp][loc] = np.zeros(len(
                EDP_specs[edp][loc])).tolist()
    #print(envelopeDict)

    # initialize dictionary of time history EDPs
    time_analysis = np.zeros(nsteps * 5)
    acc_history = {}
    for floor in range(stories + 1):
        acc_history.update(
            {floor: {
                1: time_analysis.copy(),
                2: time_analysis.copy()
            }})

    ops.wipeAnalysis()

    ops.constraints(
        'Transformation'
    )  # handles boundary conditions based on transformation equation method
    ops.numberer('RCM')  # renumber dof's to minimize band-width (optimization)
    ops.system('UmfPack'
               )  # constructs sparse system of equations using UmfPack solver
    ops.test(
        'NormDispIncr', tol, maxiter
    )  # tests for convergence using norm of left-hand side of matrix equation
    ops.algorithm(
        'NewtonLineSearch'
    )  # use Newton's solution algorithm: updates tangent stiffness at every iteration
    ops.integrator(
        'Newmark', 0.5,
        0.25)  # Newmark average acceleration method for numerical integration
    ops.analysis('Transient')  # define type of analysis: time-dependent

    # initialize variables
    maxDiv = 1024
    minDiv = subSteps
    step = 0
    ok = 0
    breaker = 0
    count = 0

    while step < nsteps and ok == 0 and breaker == 0:
        step = step + 1  # take 1 step
        ok = 2
        div = minDiv
        length = maxDiv
        while div <= maxDiv and length > 0 and breaker == 0:
            stepSize = dt / div
            # perform analysis for one increment; will return 0 if no convergence issues
            ok = ops.analyze(1, stepSize)
            if ok == 0:
                count = count + 1
                length = length - maxDiv / div

                floor = 1

                while floor <= stories:

                    # check if drift limits are satisfied
                    # check X direction drifts (direction 1)
                    drift_x = abs(
                        ops.nodeDisp(node_tags[1], 1) -
                        ops.nodeDisp(node_tags[0], 1)) / height
                    if drift_x >= driftLimit:
                        breaker = 1

                    # check Y direction drifts (direction 2)
                    drift_y = abs(
                        ops.nodeDisp(node_tags[1], 2) -
                        ops.nodeDisp(node_tags[0], 2)) / height
                    if drift_y >= driftLimit:
                        breaker = 1

                    # save parameter values in recording dictionaries at every step
                    time_analysis[count] = time_analysis[count - 1] + stepSize

                    envelopeDict['PID'][floor][0] = max(
                        drift_x, envelopeDict['PID'][floor][0])
                    envelopeDict['PID'][floor][1] = max(
                        drift_y, envelopeDict['PID'][floor][1])

                    floor = floor + 1

                for floor in range(stories + 1):
                    for dof in [1, 2]:
                        acc_history[floor][dof][count] = ops.nodeAccel(
                            node_tags[floor], dof)

            else:
                div = div * 2
                print("Number of increments increased to ", str(div))

        # end analysis once drift limit has been reached
        if breaker == 1:
            ok = 1
            print("Collapse drift has been reached")

    print("Number of analysis steps completed: {}".format(count))

    # remove extra zeros from the end of the time history
    time_analysis = time_analysis[1:count + 1]

    # generate time array from recording
    time_record = np.linspace(0, nsteps * dt, num=nsteps, endpoint=False)

    # remove extra zeros from accel time history, add GM to obtain absolute a
    # acceleration, and record envelope value
    GMX_interp = np.interp(time_analysis, time_record, GMX)
    GMY_interp = np.interp(time_analysis, time_record, GMY)
    for floor in range(0, stories + 1):
        # X direction
        envelopeDict['PFA'][floor][0] = max(
            abs(np.asarray(acc_history[floor][1][1:count + 1]) + GMX_interp))
        # Y direction
        envelopeDict['PFA'][floor][1] = max(
            abs(np.asarray(acc_history[floor][2][1:count + 1]) + GMY_interp))

    return envelopeDict
Пример #9
0
def RunAnalysis():
    # ----------------------------
    # Start of model generation
    # ----------------------------
    # remove existing model
    ops.wipe()
    ops.model("BasicBuilder", "-ndm", 3, "-ndf", 6)

    # set default units
    ops.defaultUnits("-force", "kip", "-length", "in", "-time", "sec", "-temp",
                     "F")

    # Define the section
    # ------------------
    #                                       secTag  E     nu     h    rho
    ops.section("ElasticMembranePlateSection", 1, 3.0E3, 0.25, 1.175, 1.27)

    # Define geometry
    # ---------------
    # these should both be even

    nx = 10
    ny = 2

    # loaded nodes
    mid = int(((nx + 1) * (ny + 1) + 1) / 2)
    side1 = int((nx + 2) / 2)
    side2 = int((nx + 1) * (ny + 1) - side1 + 1)

    # generate the nodes and elements
    #          numX numY startNode startEle eleType eleArgs? coords?
    ops.block2D(nx, ny, 1, 1, "ShellMITC4", 1, 1, -20.0, 0.0, 0.0, 2, -20.0,
                0.0, 40.0, 3, 20.0, 0.0, 40.0, 4, 20.0, 0.0, 0.0, 5, -10.0,
                10.0, 20.0, 7, 10.0, 10.0, 20.0, 9, 0.0, 10.0, 20.0)

    # define the boundary conditions
    ops.fixZ(0.0, 1, 1, 1, 0, 1, 1)
    ops.fixZ(40.0, 1, 1, 1, 0, 1, 1)

    ops.mass(20, 10.0, 10.0, 10.0, 0.0, 0.0, 0.0)

    # create a Linear time series
    ops.timeSeries("Linear", 1)

    # add some loads
    ops.pattern("Plain", 1, 1, "-fact", 1.0)
    ops.load(mid, 0.0, -0.50, 0.0, 0.0, 0.0, 0.0)
    ops.load(side1, 0.0, -0.25, 0.0, 0.0, 0.0, 0.0)
    ops.load(side2, 0.0, -0.25, 0.0, 0.0, 0.0, 0.0)

    # ------------------------
    # Start of static analysis
    # ------------------------
    # Load control with variable load steps
    #                            init  Jd  min  max
    ops.integrator("LoadControl", 1.0, 1, 1.0, 10.0)
    ops.test("EnergyIncr", 1.0E-10, 20, 0)
    ops.algorithm("Newton")
    ops.numberer("RCM")
    ops.constraints("Plain")
    ops.system("SparseGeneral", "-piv")
    ops.analysis("Static")
    ops.analyze(5)

    # ---------------------------------------
    # Create and Perform the dynamic analysis
    # ---------------------------------------
    # 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)

    Model = 'test'
    LoadCase = 'Transient'
    LoadCase2 = 'Transient_5s'
    opp.createODB(Model, LoadCase, Nmodes=3, recorders=[])
    opp.createODB(Model, LoadCase2, Nmodes=3, deltaT=5., recorders=[])

    # Create the transient analysis
    ops.test("EnergyIncr", 1.0E-10, 20, 0)
    ops.algorithm("Newton")
    ops.numberer("RCM")
    ops.constraints("Plain")
    ops.system("SparseGeneral", "-piv")
    ops.integrator("Newmark", 0.50, 0.25)
    ops.analysis("Transient")

    # Perform the transient analysis (20 sec)
    ops.analyze(100, 0.2)
Пример #10
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]
Пример #11
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
Пример #12
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
Пример #13
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')
Пример #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("========================================")
Пример #15
0
# Permform the conversion from SMD record to OpenSees record
dt, nPts = ReadRecord.ReadRecord(record + '.at2', record + '.dat')

# Set time series to be passed to uniform excitation
ops.timeSeries('Path', 7, '-filePath', record + '.dat', '-dt', dt, '-factor',
               g)

# Create UniformExcitation load pattern
#                         tag dir
ops.pattern('UniformExcitation', 7, 1, '-accel', 7)

# set the rayleigh damping factors for nodes & elements
ops.rayleigh(0.4274, 0.005827, 0.0, 0.0)

# Delete the old analysis and all it's component objects
ops.wipeAnalysis()

# Create the system of equation, a banded general storage scheme
ops.system('BandGeneral')

# Create the constraint handler, a plain handler as homogeneous boundary
ops.constraints('Transformation')

# Create the convergence test, the norm of the residual with a tolerance of
# 1e-12 and a max number of iterations of 10
ops.test('NormDispIncr', 1.0e-4, 100)

# Create the solution algorithm, a Newton-Raphson algorithm
ops.algorithm('Newton')

# Create the DOF numberer, the reverse Cuthill-McKee algorithm
Пример #16
0
#import os
import math
op.wipe()

from InelasticFiberSection import *
Dmax = 0.05 * LCol
Dincr = 0.001 * LCol
Hload = Weight
maxNumIter = 6
tol = 1e-8

op.timeSeries('Linear', 2)
op.pattern('Plain', 200, 2)
op.load(2, Hload, 0.0, 0.0)

op.wipeAnalysis()
op.constraints('Plain')
op.numberer('Plain')
op.system('BandGeneral')
op.test('EnergyIncr', Tol, maxNumIter)
op.algorithm('Newton')

op.integrator('DisplacementControl', IDctrlNode, IDctrlDOF, Dincr)
op.analysis('Static')

Nsteps = int(Dmax / Dincr)

ok = op.analyze(Nsteps)
print(ok)

# for gravity analysis, load control is fine, 0.1 is the load factor increment (http://opensees.berkeley.edu/wiki/index.php/Load_Control)
def run_sensitivity_pushover_analysis(ctrlNode,
                                      baseNodes,
                                      dof,
                                      Dincr,
                                      max_disp,
                                      SensParam,
                                      IOflag=False):
    """
    Run pushover analysis with sensitivity
    """
    ops.wipeAnalysis()
    start_time = time.time()
    ops.loadConst("-time", 0.0)

    title("Running Displacement-Control Pushover Sensitivity Analysis ...")

    testType = "NormDispIncr"  # EnergyIncr
    tolInit = 1.0E-8
    iterInit = 10  # Set the initial Max Number of Iterations
    algorithmType = "Newton"  # Set the algorithm type

    ops.system("BandGeneral")
    ops.constraints("Transformation")
    ops.numberer("RCM")
    ops.test(testType, tolInit, iterInit)
    ops.algorithm(algorithmType)
    # Change the integration scheme to be displacement control
    #                                     node      dof  init Jd min max
    ops.integrator("DisplacementControl", ctrlNode, dof, Dincr)
    ops.analysis("Static")
    ops.sensitivityAlgorithm(
        "-computeAtEachStep"
    )  # automatically compute sensitivity at the end of each step

    if IOflag:
        print(
            f"Single Pushover: Push node {ctrlNode} to {max_disp} {LunitTXT}.\n"
        )

    # Set some parameters
    tCurrent = ops.getTime()
    currentStep = 1

    outputs = {
        "time": np.array([]),
        "disp": np.array([]),
        "force": np.array([]),
    }

    for sens in SensParam:
        outputs[f"sensLambda_{sens}"] = np.array([]),

    nodeList = []
    for node in baseNodes:
        nodeList.append(f"- ops.nodeReaction({node}, dof) ")

    nodeList = "".join(nodeList)
    currentDisp = ops.nodeDisp(ctrlNode, dof)
    ok = 0

    while ok == 0 and currentDisp < max_disp:
        ops.reactions()
        ok = ops.analyze(1)
        tCurrent = ops.getTime()
        currentDisp = ops.nodeDisp(ctrlNode, dof)

        if IOflag:
            print(
                f"Current displacement ==> {ops.nodeDisp(ctrlNode, dof):.3f} {LunitTXT}"
            )

        # if the analysis fails try initial tangent iteration
        if ok != 0:
            print("\n==> Trying relaxed convergence...")
            ops.test(testType, tolInit / 0.01, iterInit * 50)
            ok = ops.analyze(1)
            if ok == 0:
                print("==> that worked ... back to default analysis...\n")
            ops.test(testType, tolInit, iterInit)

        if ok != 0:
            print("\n==> Trying Newton with initial then current...")
            ops.test(testType, tolInit / 0.01, iterInit * 50)
            ops.algorithm("Newton", "-initialThenCurrent")
            ok = ops.analyze(1)
            if ok == 0:
                print("==> that worked ... back to default analysis...\n")
            ops.algorithm(algorithmType)
            ops.test(testType, tolInit, iterInit)

        if ok != 0:
            print("\n==> Trying ModifiedNewton with initial...")
            ops.test(testType, tolInit / 0.01, iterInit * 50)
            ops.algorithm("ModifiedNewton", "-initial")
            ok = ops.analyze(1)
            if ok == 0:
                print("==> that worked ... back to default analysis...\n")
            ops.algorithm(algorithmType)
            ops.test(testType, tolInit, iterInit)

        currentStep += 1
        tCurrent = ops.getTime()

        outputs["time"] = np.append(outputs["time"], tCurrent)
        outputs["disp"] = np.append(outputs["disp"],
                                    ops.nodeDisp(ctrlNode, dof))
        outputs["force"] = np.append(outputs["force"], eval(nodeList))

        for sens in SensParam:
            # sensLambda(patternTag, paramTag)
            outputs[f"sensLambda_{sens}"] = np.append(
                outputs[f"sensLambda_{sens}"], ops.sensLambda(1, sens))

    # Print a message to indicate if analysis completed succesfully or not
    if ok == 0:
        title("Pushover Analysis Completed Successfully!")
    else:
        title("Pushover Analysis Completed Failed!")

    print(
        f"Analysis elapsed time is {(time.time() - start_time):.3f} seconds.\n"
    )

    return outputs
Пример #18
0
def analisis_opensees(path, permutaciones):  #helper, #win
    ops.wipe()

    # bucle para generar los x análisis
    for i in range(len(permutaciones)):

        perfil = str(permutaciones[i][0])
        nf = permutaciones[i][2]
        amort = permutaciones[i][3]
        den = permutaciones[i][4]
        vel = permutaciones[i][5]
        capas = len(permutaciones[i][6])
        nstep = permutaciones[i][30]
        dt = float(permutaciones[i][31])

        # creación de elementos
        sElemX = permutaciones[i][1]  # elementos en X
        sElemZ = permutaciones[i][46]  # espesor en Z

        # =============================================================================
        #         ######## geometría de la columna ######
        # =============================================================================
        # límite entre capas
        limite_capa = []
        anterior = 0
        for j in range(capas):
            espesor = permutaciones[i][8][j]

            limite_capa.append(espesor + anterior)
            anterior = limite_capa[j]
            print('Límite de capa: ' + str(limite_capa[j]))

        # creación de elementos y nodos en x
        nElemX = 1  # elementos en x
        nNodeX = 2 * nElemX + 1  # nodos en x

        # creación de elementos y nodos para z
        nElemZ = 1

        # creación de elementos y nodos en Y y totales
        nElemY = []  # elementos en y
        sElemY = []  # dimension en y
        nElemT = 0
        for j in range(capas):
            espesor = permutaciones[i][8][j]

            nElemY.append(2 * espesor)
            nElemT += nElemY[j]
            print('Elementos en capa ' + str(j + 1) + ': ' + str(nElemY[j]))
            sElemY.append(permutaciones[i][8][j] / nElemY[j])
            print('Tamaño de los elementos en capa ' + str(j + 1) + ': ' +
                  str(sElemY[j]) + '\n')

        # number of nodes in vertical direction in each layer
        nNodeY = []  # dimension en y
        nNodeT = 0
        s = 0
        for j in range(capas - 1):
            nNodeY.append(4 * nElemY[j])
            nNodeT += nNodeY[j]
            s += 1
            print('Nodos en capa ' + str(j + 1) + ': ' + str(nNodeY[j]))

        nNodeY.append(4 * (nElemY[-1] + 1))
        nNodeT += nNodeY[-1]
        print('Nodos en capa ' + str(s + 1) + ': ' + str(nNodeY[s]))
        print('Nodos totales: ' + str(nNodeT))

        #win.ui.progressBar.setValue(15)

        # =============================================================================
        #         ######### Crear nodos del suelo ##########
        # =============================================================================
        # creación de nodos de presión de poros
        ops.model('basic', '-ndm', 3, '-ndf', 4)

        with open(path + '/Post-proceso/' + perfil + '/ppNodesInfo.dat',
                  'w') as f:
            count = 0.0
            yCoord = 0.0
            nodos = []
            dryNode = []
            altura_nf = 10 - nf

            for k in range(capas):
                for j in range(0, int(nNodeY[k]), 4):
                    ops.node(j + count + 1, 0.0, yCoord, 0.0)
                    ops.node(j + count + 2, 0.0, yCoord, sElemZ)
                    ops.node(j + count + 3, sElemX, yCoord, sElemZ)
                    ops.node(j + count + 4, sElemX, yCoord, 0.0)

                    f.write(
                        str(int(j + count + 1)) + '\t' + str(0.0) + '\t' +
                        str(yCoord) + '\t' + str(0.0) + '\n')
                    f.write(
                        str(int(j + count + 2)) + '\t' + str(0.0) + '\t' +
                        str(yCoord) + '\t' + str(sElemZ) + '\n')
                    f.write(
                        str(int(j + count + 3)) + '\t' + str(sElemX) + '\t' +
                        str(yCoord) + '\t' + str(sElemZ) + '\n')
                    f.write(
                        str(int(j + count + 4)) + '\t' + str(sElemX) + '\t' +
                        str(yCoord) + '\t' + str(0.0) + '\n')

                    nodos.append(str(j + count + 1))
                    nodos.append(str(j + count + 2))
                    nodos.append(str(j + count + 3))
                    nodos.append(str(j + count + 4))

                    #designate node sobre la superficie de agua
                    if yCoord >= altura_nf:
                        dryNode.append(j + count + 1)
                        dryNode.append(j + count + 2)
                        dryNode.append(j + count + 3)
                        dryNode.append(j + count + 4)

                    yCoord = (yCoord + sElemY[k])

                count = (count + nNodeY[k])

        print("Finished creating all soil nodes...")

        # =============================================================================
        #         ####### Condiciones de contorno en la base de la columna #########
        # =============================================================================
        ops.fix(1, *[0, 1, 1, 0])
        ops.fix(2, *[0, 1, 1, 0])
        ops.fix(3, *[0, 1, 1, 0])
        ops.fix(4, *[0, 1, 1, 0])
        ops.equalDOF(1, 2, 1)
        ops.equalDOF(1, 3, 1)
        ops.equalDOF(1, 4, 1)

        print('Fin de creación de nodos de la base de la columna\n\n')

        # =============================================================================
        #         ####### Condiciones de contorno en los nudos restantes #########
        # =============================================================================

        count = 0
        for k in range(5, int(nNodeT + 1), 4):
            ops.equalDOF(k, k + 1, *[1, 2, 3])
            ops.equalDOF(k, k + 2, *[1, 2, 3])
            ops.equalDOF(k, k + 3, *[1, 2, 3])

        print('Fin de creación equalDOF para nodos de presión de poros\n\n')

        for j in range(len(dryNode)):
            ops.fix(dryNode[j], *[0, 0, 0, 1])

        print("Finished creating all soil boundary conditions...")

        # =============================================================================
        #         ####### crear elemento y material de suelo #########
        # =============================================================================

        cargas = []
        for j in range(capas):
            pendiente = permutaciones[i][9][j]
            slope = math.atan(pendiente / 100)

            tipo_suelo = permutaciones[i][6][j]
            rho = permutaciones[i][10][j]
            Gr = permutaciones[i][12][j]
            Br = permutaciones[i][13][j]
            fric = permutaciones[i][15][j]
            refpress = permutaciones[i][18][j]
            gmax = permutaciones[i][19][j]
            presscoef = permutaciones[i][20][j]
            surf = permutaciones[i][21][j]
            ev = permutaciones[i][22][j]
            cc1 = permutaciones[i][23][j]
            cc3 = permutaciones[i][24][j]
            cd1 = permutaciones[i][25][j]
            cd3 = permutaciones[i][26][j]
            ptang = permutaciones[i][27][j]
            coh = permutaciones[i][28][j]

            if tipo_suelo == 'No cohesivo':
                if float(surf) > 0:
                    ops.nDMaterial('PressureDependMultiYield02', j + 1, 3.0,
                                   rho, Gr, Br, fric, gmax, refpress,
                                   presscoef, ptang, cc1, cc3, cd1, cd3,
                                   float(surf), 5.0, 3.0, *[1.0, 0.0], ev,
                                   *[0.9, 0.02, 0.7, 101.0])
                else:
                    ops.nDMaterial('PressureDependMultiYield02', j + 1, 3.0,
                                   rho, Gr, Br, fric, gmax, refpress,
                                   presscoef, ptang, cc1, cc3, cd1, cd3,
                                   float(surf), *permutaciones[i][29][j], 5.0,
                                   3.0, *[1.0,
                                          0.0], ev, *[0.9, 0.02, 0.7, 101.0])

            cargas.append(
                [0.0, -9.81 * math.cos(slope), -9.81 * math.sin(slope)])

        print('Fin de la creación de material de suelo\n\n')

        #-----------------------------------------------------------------------------------------
        #  5. CREATE SOIL ELEMENTS
        #-----------------------------------------------------------------------------------------

        count = 0
        alpha = 1.5e-6

        with open(path + '/Post-proceso/' + perfil + '/ppElemInfo.dat',
                  'w') as f:
            # crear elemento de suelo
            for k in range(capas):
                for j in range(int(nElemY[k])):
                    nI = 4 * (j + count + 1) - 3
                    nJ = nI + 1
                    nK = nI + 2
                    nL = nI + 3
                    nM = nI + 4
                    nN = nI + 5
                    nO = nI + 6
                    nP = nI + 7
                    f.write(
                        str(j + count + 1) + '\t' + str(nI) + '\t' + str(nJ) +
                        '\t' + str(nK) + '\t' + str(nL) + '\t' + str(nM) +
                        '\t' + str(nN) + '\t' + str(nO) + '\t' + str(nP) +
                        '\n')

                    Bc = permutaciones[i][14][k]
                    ev = permutaciones[i][22][k]

                    ops.element('SSPbrickUP', (j + count + 1),
                                *[nI, nJ, nK, nL, nM, nN, nO,
                                  nP], (k + 1), float(Bc), 1.0, 1.0, 1.0, 1.0,
                                float(ev), alpha, cargas[k][0], cargas[k][1],
                                cargas[k][2])

                count = (count + int(nElemY[k]))
        print('Fin de la creación del elemento del suelo\n\n')

        #win.ui.progressBar.setValue(25)

        # =============================================================================
        #         ######### Amortiguamiento de Lysmer ##########
        # =============================================================================

        ops.model('basic', '-ndm', 3, '-ndf', 3)

        # definir nodos y coordenadas del amortiguamiento
        dashF = nNodeT + 1
        dashX = nNodeT + 2
        dashZ = nNodeT + 3

        ops.node(dashF, 0.0, 0.0, 0.0)
        ops.node(dashX, 0.0, 0.0, 0.0)
        ops.node(dashZ, 0.0, 0.0, 0.0)

        # definir restricciones para los nodos de amortiguamiento
        ops.fix(dashF, 1, 1, 1)
        ops.fix(dashX, 0, 1, 1)
        ops.fix(dashZ, 1, 1, 0)

        # definir equalDOF para el amortiguamiento en la base del suelo
        ops.equalDOF(1, dashX, 1)
        ops.equalDOF(1, dashZ, 3)

        print(
            'Fin de la creación de condiciones de contorno de los nodos de amortiguamiento\n\n'
        )

        # definir el material de amortiguamiento
        colArea = sElemX * sElemZ
        dashpotCoeff = vel * den * colArea
        ops.uniaxialMaterial('Viscous', capas + 1, dashpotCoeff, 1.0)

        # definir el elemento
        ops.element('zeroLength', nElemT + 1, *[dashF, dashX], '-mat',
                    capas + 1, '-dir', *[1])
        ops.element('zeroLength', nElemT + 2, *[dashF, dashZ], '-mat',
                    capas + 1, '-dir', *[3])

        print('Fin de la creación del elemento de amortiguamiento\n\n')

        #-----------------------------------------------------------------------------------------
        #  9. DEFINE ANALYSIS PARAMETERS
        #-----------------------------------------------------------------------------------------

        # amortiguamiento de Rayleigh
        # frecuencia menor
        omega1 = 2 * math.pi * 0.2
        # frecuencia mayor
        omega2 = 2 * math.pi * 20

        a0 = 2.0 * (amort / 100) * omega1 * omega2 / (omega1 + omega2)
        a1 = 2.0 * (amort / 100) / (omega1 + omega2)
        print('Coeficientes de amortiguamiento' + '\n' + 'a0: ' +
              format(a0, '.6f') + '\n' + 'a1: ' + format(a1, '.6f') + '\n\n')

        #win.ui.progressBar.setValue(35)

        # =============================================================================
        #         ######## Determinación de análisis estático #########
        # =============================================================================
        #---DETERMINE STABLE ANALYSIS TIME STEP USING CFL CONDITION
        # se determina a partir de un análisis transitorio de largo tiempo
        duration = nstep * dt

        # tamaño mínimo del elemento y velocidad máxima
        minSize = sElemY[0]
        vsMax = permutaciones[i][11][0]
        for j in range(1, capas):
            if sElemY[j] < minSize:
                minSize = sElemY[j]
            if permutaciones[i][11][j] > vsMax:
                vsMax = permutaciones[i][11][j]

        # trial analysis time step
        kTrial = minSize / (vsMax**0.5)

        # tiempo de análisis y pasos de tiempo
        if dt <= kTrial:
            nStep = nstep
            dT = dt
        else:
            nStep = int(math.floor(duration / kTrial) + 1)
            dT = duration / nStep

        print('Número de pasos en el análisis: ' + str(nStep) + '\n')
        print('Incremento de tiempo: ' + str(dT) + '\n\n')

        #----------------------------------------------------------------------------------------
        #  7. GRAVITY ANALYSIS
        #-----------------------------------------------------------------------------------------
        ops.model('basic', '-ndm', 3, '-ndf', 4)

        ops.updateMaterialStage('-material', int(k + 1), '-stage', 0)

        # algoritmo de análisis estático
        ops.constraints(permutaciones[i][32][0],
                        float(permutaciones[i][32][1]),
                        float(permutaciones[i][32][2]))
        ops.test(permutaciones[i][34][0], float(permutaciones[i][34][1]),
                 int(permutaciones[i][34][2]), int(permutaciones[i][34][3]))
        ops.algorithm(permutaciones[i][38][0])
        ops.numberer(permutaciones[i][33][0])
        ops.system(permutaciones[i][36][0])
        ops.integrator(permutaciones[i][35][0], float(permutaciones[i][35][1]),
                       float(permutaciones[i][35][2]))
        ops.analysis(permutaciones[i][37][0])

        print('Inicio de análisis estático elástico\n\n')

        ops.start()
        ops.analyze(20, 5.0e2)

        print('Fin de análisis estático elástico\n\n')

        #win.ui.progressBar.setValue(40)

        # update materials to consider plastic behavior

        # =============================================================================

        ops.updateMaterialStage('-material', int(k + 1), '-stage', 1)

        # =============================================================================

        # plastic gravity loading
        print('Inicio de análisis estático plástico\n\n')

        ok = ops.analyze(40, 5.0e-2)

        if ok != 0:
            error = 'Error de convergencia en análisis estático de modelo' + str(
                perfil) + '\n\n'
            print(error)

            break

        print('Fin de análisis estático plástico\n\n')

        #-----------------------------------------------------------------------------------------
        #  11. UPDATE ELEMENT PERMEABILITY VALUES FOR POST-GRAVITY ANALYSIS
        #-----------------------------------------------------------------------------------------

        ini = 1
        aum = 0
        sum = 0
        for j in range(capas):
            #Layer 3
            ops.setParameter(
                '-val', permutaciones[i][16][j],
                ['-eleRange',
                 int(ini + aum),
                 int(nElemY[j] + sum)], 'xPerm')
            ops.setParameter(
                '-val', permutaciones[i][17][j],
                ['-eleRange',
                 int(ini + aum),
                 int(nElemY[j] + sum)], 'yPerm')
            ops.setParameter(
                '-val', permutaciones[i][16][j],
                ['-eleRange',
                 int(ini + aum),
                 int(nElemY[j] + sum)], 'zPerm')

            ini = nElemY[j] + sum
            sum += nElemY[j]
            aum = 1

        print("Finished updating permeabilities for dynamic analysis...")

        # =============================================================================
        #         ########### Grabadores dinámicos ##########
        # =============================================================================

        ops.setTime(0.0)
        ops.wipeAnalysis()
        ops.remove('recorders')

        # tiempo de la grabadora
        recDT = 10 * dt
        path_acel = path + '/Post-proceso/' + perfil + '/dinamico/aceleraciones/'

        ops.recorder('Node', '-file', path_acel + 'accelerationx.out', '-time',
                     '-dT', recDT, '-node', *nodos, '-dof', 1, 'accel')

        print('Fin de creación de grabadores\n\n')
        #win.ui.progressBar.setValue(50)

        # =============================================================================
        #         ######### Determinación de análisis dinámico ##########
        # =============================================================================

        # objeto de serie temporal para el historial de fuerza

        path_vel = path + '/Pre-proceso/' + perfil + '/TREASISL2.txt'

        ops.timeSeries('Path', 1, '-dt', dt, '-filePath', path_vel, '-factor',
                       dashpotCoeff)

        ops.pattern('Plain', 10, 1)
        ops.load(1, *[1.0, 0.0, 0.0, 0.0])  #CAMBIO REALIZADO OJO

        print('Fin de creación de carga dinámica\n\n')

        # algoritmo de análisis dinámico
        ops.constraints(permutaciones[i][39][0],
                        float(permutaciones[i][39][1]),
                        float(permutaciones[i][39][2]))
        ops.test(permutaciones[i][41][0], float(permutaciones[i][41][1]),
                 int(permutaciones[i][41][2]), int(permutaciones[i][41][3]))
        ops.algorithm(permutaciones[i][45][0])
        ops.numberer(permutaciones[i][40][0])
        ops.system(permutaciones[i][43][0])
        ops.integrator(permutaciones[i][42][0], float(permutaciones[i][42][1]),
                       float(permutaciones[i][42][2]))
        ops.analysis(permutaciones[i][44][0])
        # =============================================================================
        #         ops.rayleigh(a0, a1, 0.0, 0.0)
        # =============================================================================

        print('Inicio de análisis dinámico\n\n')
        #win.ui.progressBar.setValue(85)
        ok = ops.analyze(nStep, dT)

        if ok != 0:
            error = 'Error de convergencia en análisis dinámico de modelo' + str(
                permutaciones[i][0]) + '\n\n'
            print(error)
            curTime = ops.getTime()
            mTime = curTime
            print('cursTime:' + str(curTime))
            curStep = (curTime / dT)
            print('cursStep:' + str(curStep))
            rStep = (nStep - curStep) * 2.0
            remStep = int(nStep - curStep) * 2.0
            print('remSTep:' + str(curStep))
            dT = (dT / 2)
            print('dT:' + str(dT))

            ops.analyze(remStep, dT)

            if ok != 0:
                error = 'Error de convergencia en análisis dinámico de modelo' + str(
                    permutaciones[i][0]) + '\n\n'
                print(error)
                curTime = ops.getTime()
                print('cursTime:' + str(curTime))
                curStep = (curTime - mTime) / dT
                print('cursStep:' + str(curStep))
                remStep = int(rStep - curStep) * 2
                print('remSTep:' + str(curStep))
                dT = (dT / 2)
                print('dT:' + str(dT))

                ops.analyze(remStep, dT)

        print('Fin de análisis dinámico\n\n')

    ops.wipe()
Пример #19
0
def run_dynamic_analysis_w_rayleigh_damping(dict_of_hinges,
                                            dict_of_disp_nodes,
                                            dict_of_rxn_nodes,
                                            zeta,
                                            initialOrTangent='initial',
                                            parent_dir=os.getcwd()):

    # remove any existing analysis data
    op.wipeAnalysis()

    # define a time series to add the ground motion
    op.timeSeries('Path', 2, '-dt', 0.01, '-filePath', 'BM68elc.acc',
                  '-factor', 3.0 * g)
    op.pattern('UniformExcitation', 2, 1, '-accel', 2)

    # uncomment/comment the code below to run bideirectional/unidirectional ground motion analysis
    #    op.timeSeries('Path', 3, '-dt', 0.01, '-filePath', 'BM68elc.acc', '-factor', 1.0*g)
    #    op.pattern('UniformExcitation', 3, 2, '-accel', 3)

    op.constraints('Transformation')
    op.numberer('RCM')
    op.system('UmfPack')
    #    op.test('NormDispIncr', 1e-2, 100000, 0, 0)
    op.test('EnergyIncr', 1e-4, 1e4, 0, 2)

    # available set of algorithms if the default fails
    backup_algos = {
        'Modified Newton w/ Initial Stiffness': ['ModifiedNewton', '-initial'],
        'Newton with Line Search': [
            'NewtonLineSearch', 'tol', 1e-3, 'maxIter', 1e5, 'maxEta', 10,
            'minEta', 1e-2
        ],
    }

    # define the default algorithm to be used for this analysis
    op.algorithm('KrylovNewton', 'maxDim', 3)

    # define the integrator to be used for this analysis from the set of available integrators in opensees
    alpha = 0.67
    op.integrator(
        'HHT',
        alpha)  # can be either of: ('HHT', alpha), ('Newmark', 0.5, 0.25)

    # define the type of analysis to be performed
    op.analysis('Transient')

    # obtain the modal analysis
    eigenValues = modal_response(numEigen)
    # get periods from the modal analsis
    periods = 2 * math.pi / np.sqrt(eigenValues)

    w1 = (eigenValues[0]**0.5)
    w2 = (eigenValues[0]**0.5) / 0.384
    a0 = zeta * 2 * w1 * w2 / (w1 + w2)
    a1 = zeta * 2 / (w1 + w2)

    print('\nRayleigh Damping Coefficients:')
    print(f'\talpha: {a0}')
    print(f'\tbeta : {a1}\n')

    if initialOrTangent == 'tangent':
        op.rayleigh(a0, a1, 0, 0)
    else:
        op.rayleigh(a0, 0, a1, 0)

    # setup to record analysis data
    setup_recorders(dict_of_disp_nodes, dict_of_rxn_nodes, dict_of_hinges,
                    initialOrTangent, parent_dir)

    total_run_time = 50  # seconds
    time_step = 0.01  # seconds
    total_num_of_steps = total_run_time / time_step

    # default initialization of constants to be used in the execution loop
    failed = 0
    time = 0
    algo = 'Krylov-Newton'
    pbar = tqdm(total=total_num_of_steps)

    # execution loop
    # this execution loop tries to use krylov-Newton until it works, when this fails it iterate through set of
    # algorithms until it finds a solution, if it is not able to find a solution with any algorithm, the loop ends.
    # Whereas if it is able to find a solution with any of the algorithms, it switches back to krylov-Newton
    while time <= total_run_time and failed == 0:
        failed = op.analyze(1, time_step)

        if failed:
            print(f'\n{algo} failed. Trying other algorithms...')

            for alg, algo_args in backup_algos.items():
                print(f'\nTrying {alg}...')
                op.algorithm(*algo_args)
                failed = op.analyze(1, time_step)

                if failed:
                    continue
                else:
                    algo = 'Krylov-Newton'
                    print(f'\n{alg} worked.\n\nMoving back to {algo}')
                    op.algorithm('KrylovNewton', 'maxDim', 3)
                    break

            print(''.center(100, '-'))

        pbar.update(1)
        time = op.getTime()

    op.wipe()

    # move output files to results directory
    list_of_out_files = [
        fname for fname in os.listdir() if fname.endswith('.out')
    ]
    for fname in list_of_out_files:
        shutil.move(os.path.join(os.getcwd(), fname),
                    os.path.join(parent_dir, fname))

    return periods, eigenValues
Пример #20
0
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
Пример #21
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("=========================================")