def step(self, action=0):
        self.time = op.getTime()
        assert (self.time < self.analysis_time)

        # 選ばれたアクションに応じて減衰定数を変化させる
        self.h = self.action[action]
        self.hs.append(self.h)
        self.beta_k = 2 * self.h / self.w0
        op.rayleigh(self.alpha_m, self.beta_k, self.beta_k_init,
                    self.beta_k_comm)

        op.analyze(1, self.dt)
        op.reactions()

        self.dis = op.nodeDisp(self.top_node, 1)
        self.vel = op.nodeVel(self.top_node, 1)
        self.acc = op.nodeAccel(self.top_node, 1)
        self.a_acc = self.acc + self.values[self.i]
        self.force = -op.nodeReaction(self.bot_node,
                                      1)  # Negative since diff node

        self.resp["time"].append(self.time)
        self.resp["dis"].append(self.dis)
        self.resp["vel"].append(self.vel)
        self.resp["acc"].append(self.acc)
        self.resp["a_acc"].append(self.a_acc)
        self.resp["force"].append(self.force)

        next_time = op.getTime()
        self.done = next_time >= self.analysis_time

        self.i_pre = self.i
        self.i += 1
        self.i_next = self.i + 1 if not self.done else self.i
        return self.reward, self.done
Example #2
0
def test_ele_load_uniform():
    osi = o3.OpenSeesInstance(ndm=2, state=3)
    ele_len = 2.0
    coords = [[0, 0], [ele_len, 0]]
    ele_nodes = [o3.node.Node(osi, *coords[x]) for x in range(len(coords))]
    transf = o3.geom_transf.Linear2D(osi, [])
    ele = o3.element.ElasticBeamColumn2D(osi,
                                         ele_nodes=ele_nodes,
                                         area=1.0,
                                         e_mod=1.0,
                                         iz=1.0,
                                         transf=transf,
                                         mass=1.0,
                                         c_mass="string")

    for i, node in enumerate(ele_nodes):
        if i == 0:
            o3.Fix3DOF(osi, node, o3.cc.FIXED, o3.cc.FIXED, o3.cc.FIXED)
        else:
            o3.Fix3DOF(osi, node, o3.cc.FREE, o3.cc.FIXED, o3.cc.FIXED)

    ts_po = o3.time_series.Linear(osi, factor=1)
    o3.pattern.Plain(osi, ts_po)
    udl = 10.
    o3.EleLoad2DUniform(osi, ele, w_y=-udl)

    tol = 1.0e-4
    o3.constraints.Plain(osi)
    o3.numberer.RCM(osi)
    o3.system.BandGeneral(osi)
    o3.test_check.NormDispIncr(osi, tol, 6)
    o3.algorithm.Newton(osi)
    n_steps_gravity = 1
    d_gravity = 1. / n_steps_gravity
    o3.integrator.LoadControl(osi, d_gravity, num_iter=10)
    o3.analysis.Static(osi)
    o3.analyze(osi, n_steps_gravity)
    opy.reactions()
    ele_loads = o3.get_ele_response(osi, ele, 'force')
    assert np.isclose(ele_loads[0], 0.0)
    assert np.isclose(ele_loads[1], udl * ele_len / 2)
    assert np.isclose(ele_loads[2], udl * ele_len**2 / 12)
    assert np.isclose(ele_loads[3], 0.0)
    assert np.isclose(ele_loads[4], udl * ele_len / 2)
    assert np.isclose(ele_loads[5], -udl * ele_len**2 / 12)
    assert np.isclose(o3.get_node_reaction(osi, ele_nodes[0], o3.cc.Y),
                      udl * ele_len / 2)
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
def NSProcedure(ndm, ndf, NbaysX, NbaysZ, NStr, XbayL, ZbayL, StoryH, lon, lat,
                SHL, Vso, gamma_soil, nu_soil, Re, fpc, Ec, gamma_conc, fy, E0,
                bsteel, ColTransfType, BeamEffFact, ColEffFact, g, Qsd, Ql,
                Qlr, EMs, R, Ie, StrType, BldTypCo, BldTypCm, DsgnType, dirs,
                directory):

    # The Nonlinear Static Procdure is executed in order to get responses
    # of a defined building.

    import openseespy.opensees as ops
    import OPSDefsMOD as OPSDMOD
    import OPSDefsAN as OPSDAN
    from timeit import default_timer as timer
    import ASCE716Seismic as ASCE716
    import ASCE4117
    import matplotlib.pyplot as plt
    import pickle
    import numpy as np

    for mm in range(len(NbaysX)):
        for nn in range(len(NStr)):
            for oo in range(len(Vso)):

                Teff = np.zeros(
                    (len(dirs)
                     ))  # [s][LIST] effective lateral period of building.

                for ii in range(len(dirs)):

                    time_o = timer()

                    # Some previous definitions
                    # ----------------------------
                    if DsgnType in ('conv_dsgn'):
                        flex = 'no'
                    elif DsgnType in ('ssi_dsgn'):
                        flex = 'yes'

                    # SiteClass = ASCE716.detSiteClass(Vso[oo])

                    # Unpicklin' some stored parameters from design process.
                    # ------------------------------------------------------
                    workpath = directory + '\\RegularDesign\\' + str(NbaysX[mm])+'BayX'+str(NbaysZ)+\
                        'BayZ'+str(NStr[nn])+'FLRS'+str(Vso[oo])+'.pickle'

                    with open(workpath, 'rb') as f:
                        ColDims, Colreinf, XBDims, XBreinf, ZBDims, ZBreinf, _, _, _, _, _, _, _, _, _, _ = pickle.load(
                            f)

                    # Calculation of height vector
                    # ------------------------------
                    if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'):
                        # [m][LIST] with level height starting from first level or from base if foundation flexibility is included.
                        hx = [0.0001]
                    else:
                        hx = []

                    for i in range(NStr[nn]):
                        hx.append((i + 1) * StoryH)

                    # Plan Dimensions of Building
                    B = NbaysZ * ZbayL  # [m] short side of building plan.
                    L = NbaysX[mm] * XbayL  # [m] long side of building plan.

                    # Determination of MCEr spectral acceleration parameters
                    # ------------------------------------------------------
                    (Sxs, Sx1) = ASCE4117.detSxi(lon, lat, Vso[oo], SHL)

                    # MODELING OF THE STRUCTURE USING OPENSEESPY
                    # ===========================================
                    ops.wipe()
                    OPSDMOD.ModelGen(ndm, ndf)
                    OPSDMOD.NodeGen(NbaysX[mm], NbaysZ, XbayL, ZbayL, StoryH,
                                    NStr[nn], flex)
                    OPSDMOD.MastNodeGen(NbaysX[mm],
                                        NbaysZ,
                                        XbayL,
                                        ZbayL,
                                        StoryH,
                                        NStr[nn],
                                        flex,
                                        coords=0)
                    OPSDMOD.SPConstGen(NbaysX[mm], NbaysZ, flex)
                    OPSDMOD.MPConstGen(NbaysX[mm], NbaysZ, NStr[nn], flex)
                    OPSDMOD.MatGenRCB(fpc, Ec, fy, E0, bsteel)
                    # OPSDMOD.GeomTransGen(ColTransfType,XBD=[min(XBDims[:,0]),min(XBDims[:,1])],\
                    #                      ZBD=[min(ZBDims[:,0]),min(ZBDims[:,1])],\
                    #                          ColD=[min(ColDims[:,0]),min(ColDims[:,1])])
                    OPSDMOD.GeomTransGen(
                        ColTransfType,
                        ColD=[min(ColDims[:, 0]),
                              min(ColDims[:, 1])])
                    # OPSDMOD.GeomTransGen(ColTransfType)

                    if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'):
                        # Interface elements generation for foundation flexibility considerations.
                        # =========================================================================
                        # Materials generation: stiffness constants accounting for soil flexibility.
                        # ---------------------------------------------------------------------------
                        OPSDMOD.FoundFlexMaterials(NbaysX[mm],NbaysZ,XbayL,ZbayL,Sxs,Vso[oo],gamma_soil,nu_soil,B,L,Re,\
                                                   D=0,omega_soil=0,analtype='lat')
                        # Zero-Length elements creation for connecting base nodes.
                        OPSDMOD.FoundFlexZLElements(NbaysX[mm], NbaysZ, XbayL,
                                                    ZbayL, B, L, Re)

                    OPSDMOD.ElementGen(NbaysX[mm],NbaysZ,XbayL,ZbayL,NStr[nn],StoryH,XBDims,ZBDims,\
                                               ColDims,BeamEffFact,ColEffFact,Ec,fy,EMs,\
                                                   XBreinf,ZBreinf,Colreinf,N=5,rec=0.0654,nuconc=0.2,dbar=0.025)
                    [Wx,MassInputMatr] = \
                        OPSDMOD.LumpedMassGen(NbaysX[mm],NbaysZ,XBDims,ZBDims,ColDims,gamma_conc,g,XbayL,ZbayL,NStr[nn],StoryH,Qsd,flex)
                    W = sum(Wx)  # [kN] total weight of the building

                    # GRAVITY LOADS APPLIED TO MODEL ACCORDINGO TO ASCE4117
                    # ======================================================
                    # According to ASCE4117 Section 7.2.2, equation (7-3), the combination
                    # of gravitational loads mus be as follows:
                    #       Qg = Qd + 0.25*Ql + Qs      (7-3)
                    OPSDMOD.DeadLoadGen(NbaysX[mm], NbaysZ, NStr[nn], XBDims,
                                        ZBDims, ColDims, gamma_conc)
                    OPSDMOD.SuperDeadLoadGen(NbaysX[mm], NbaysZ, NStr[nn],
                                             XbayL, ZbayL, Qsd)
                    OPSDMOD.LiveLoadGen(NbaysX[mm], NbaysZ, NStr[nn], XbayL,
                                        ZbayL, 0.25 * Ql, 0.25 * Qlr)

                    # GRAVITY-LOADS-CASE ANALYSIS.
                    # ============================
                    ops.system('ProfileSPD')
                    ops.constraints('Transformation')
                    ops.numberer('RCM')
                    ops.test('NormDispIncr', 1.0e-4, 100)
                    ops.algorithm('KrylovNewton')
                    ops.integrator('LoadControl', 1)
                    ops.analysis('Static')
                    ops.analyze(1)
                    # Vertical reactions Calculation for verification.
                    # ------------------------------------------------
                    ops.reactions()
                    YReact = 0
                    for i in range((NbaysX[mm] + 1) * (NbaysZ + 1)):
                        if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'):
                            YReact += ops.nodeReaction(int(i + 1), 2)
                        else:
                            YReact += ops.nodeReaction(int(i + 1 + 1e4), 2)

                    # ==========================================================================
                    # MODAL ANALYSIS FOR DETERMINING FUNDAMENTAL PERIOD AND ITS DIRECTION.
                    # ==========================================================================
                    (T, Tmaxver,
                     Mast) = OPSDAN.ModalAnalysis(NStr[nn], B, L, Wx, flex)
                    print(T)
                    # ==================
                    # PUSHOVER ANALYSIS
                    # ==================
                    # Lateral Force used for analysis
                    # --------------------------------
                    # Using functions from ASCE716Seismic Module.
                    (_,_,_,_,_,_,_,_,_,_,_,FxF,_,_,_) = \
                        ASCE716.ELFP(Sxs,Sx1,Vso[oo],Wx,R,Ie,hx,StrType,T[0,ii])

                    # Aplication of forces to the model.
                    # ----------------------------------
                    ops.loadConst('-time', 0.0)
                    MdeShape = OPSDMOD.POForceGen(NStr[nn], FxF, dirs[ii],
                                                  flex)

                    # =============================================
                    # First Execution of the analysis and output results.
                    # =============================================
                    (results1,dtg1,tgfactor1) = \
                        OPSDAN.POAnalysisProc(lon,lat,Vso[oo],SHL,NbaysX[mm],NbaysZ,\
                                              NStr[nn],StoryH,R,Ie,BldTypCo,BldTypCm,\
                                                  T[0,ii],W,dirs[ii],flex,\
                                                      DispIncr=0,beta=0.05,TL=8.,Tf=6.0,Npts=500,Vy=0,Te=0)  # [Disp,Force]

                    # =====================================================
                    # Determining the first approximation of values of Vy
                    # and calculation of effective fundamental period for NSP
                    # =====================================================
                    (Delta_y, V_y, Delta_d, V_d, Ke, alpha1, alpha2) = \
                        ASCE4117.IFDC(dtg1,results1)

                    Ki = Mast[ii] * 4 * np.pi**2 / T[
                        0,
                        ii]**2  # [kN/m] elastic lateral stiffness of the building.
                    Teff[ii] = T[0, ii] * (
                        Ki / Ke
                    )**0.5  # [s] effctive fundamental period of building.

                    # =============================================
                    # Second Execution of the analysis and output results.
                    # =============================================
                    ops.wipe()
                    OPSDMOD.ModelGen(ndm, ndf)
                    OPSDMOD.NodeGen(NbaysX[mm], NbaysZ, XbayL, ZbayL, StoryH,
                                    NStr[nn], flex)
                    OPSDMOD.MastNodeGen(NbaysX[mm],
                                        NbaysZ,
                                        XbayL,
                                        ZbayL,
                                        StoryH,
                                        NStr[nn],
                                        flex,
                                        coords=0)
                    OPSDMOD.SPConstGen(NbaysX[mm], NbaysZ, flex)
                    OPSDMOD.MPConstGen(NbaysX[mm], NbaysZ, NStr[nn], flex)
                    OPSDMOD.MatGenRCB(fpc, Ec, fy, E0, bsteel)
                    # OPSDMOD.GeomTransGen(ColTransfType,XBD=[min(XBDims[:,0]),min(XBDims[:,1])],\
                    #                      ZBD=[min(ZBDims[:,0]),min(ZBDims[:,1])],\
                    #                          ColD=[min(ColDims[:,0]),min(ColDims[:,1])])
                    OPSDMOD.GeomTransGen(
                        ColTransfType,
                        ColD=[min(ColDims[:, 0]),
                              min(ColDims[:, 1])])
                    # OPSDMOD.GeomTransGen(ColTransfType)

                    if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'):
                        # Interface elements generation for foundation flexibility considerations.
                        # =========================================================================
                        # Materials generation: stiffness constants accounting for soil flexibility.
                        # ---------------------------------------------------------------------------
                        OPSDMOD.FoundFlexMaterials(NbaysX[mm],NbaysZ,XbayL,ZbayL,Sxs,Vso[oo],gamma_soil,nu_soil,B,L,Re,\
                                                   D=0,omega_soil=0,analtype='lat')
                        # Zero-Length elements creation for connecting base nodes.
                        OPSDMOD.FoundFlexZLElements(NbaysX[mm], NbaysZ, XbayL,
                                                    ZbayL, B, L, Re)

                    OPSDMOD.ElementGen(NbaysX[mm],NbaysZ,XbayL,ZbayL,NStr[nn],StoryH,XBDims,ZBDims,\
                                               ColDims,BeamEffFact,ColEffFact,Ec,fy,EMs,\
                                                   XBreinf,ZBreinf,Colreinf,N=5,rec=0.0654,nuconc=0.2,dbar=0.025)
                    [Wx,MassInputMatr] = \
                        OPSDMOD.LumpedMassGen(NbaysX[mm],NbaysZ,XBDims,ZBDims,ColDims,gamma_conc,g,XbayL,ZbayL,NStr[nn],StoryH,Qsd,flex)
                    W = sum(Wx)  # [kN] total weight of the building
                    # GRAVITY LOADS APPLIED TO MODEL ACCORDINGO TO ASCE4117
                    # ======================================================
                    OPSDMOD.DeadLoadGen(NbaysX[mm], NbaysZ, NStr[nn], XBDims,
                                        ZBDims, ColDims, gamma_conc)
                    OPSDMOD.SuperDeadLoadGen(NbaysX[mm], NbaysZ, NStr[nn],
                                             XbayL, ZbayL, Qsd)
                    OPSDMOD.LiveLoadGen(NbaysX[mm], NbaysZ, NStr[nn], XbayL,
                                        ZbayL, 0.25 * Ql, 0.25 * Qlr)

                    # GRAVITY-LOADS-CASE ANALYSIS.
                    # ============================
                    ops.system('ProfileSPD')
                    ops.constraints('Transformation')
                    ops.numberer('RCM')
                    ops.test('NormDispIncr', 1.0e-4, 100)
                    ops.algorithm('KrylovNewton')
                    ops.integrator('LoadControl', 1)
                    ops.analysis('Static')
                    ops.analyze(1)
                    # ==================
                    # PUSHOVER ANALYSIS
                    # ==================
                    # Lateral Force used for analysis
                    # --------------------------------
                    # Using functions from ASCE716Seismic Module.
                    (_,_,_,_,_,_,_,_,_,_,_,FxF,_,_,_) = \
                        ASCE716.ELFP(Sxs,Sx1,Vso[oo],Wx,R,Ie,hx,StrType,Teff[ii])

                    # Aplication of forces to the model.
                    # ----------------------------------
                    ops.loadConst('-time', 0.0)
                    MdeShape = OPSDMOD.POForceGen(NStr[nn], FxF, dirs[ii],
                                                  flex)

                    # =============================================
                    # First Execution of the analysis and output results.
                    # =============================================
                    (results2,dtg2,tgfactor2) = \
                        OPSDAN.POAnalysisProc(lon,lat,Vso[oo],SHL,NbaysX[mm],NbaysZ,\
                                              NStr[nn],StoryH,R,Ie,BldTypCo,BldTypCm,\
                                                  T[0,ii],W,dirs[ii],flex,\
                                                      DispIncr=0,beta=0.05,TL=8.,Tf=6.0,Npts=500,Vy=0,Te=Teff[ii])  # [Disp,Force].

                    # =====================================================
                    # Determining the "exact"  values of Vy
                    # and calculation of effective fundamental period for NSP
                    # =====================================================
                    (Delta_y, V_y, Delta_d, V_d, Ke, alpha1, alpha2) = \
                        ASCE4117.IFDC(dtg1,results2)

                    Ki = Mast[ii] * 4 * np.pi**2 / T[
                        0,
                        ii]**2  # [kN/m] elastic lateral stiffness of the building.
                    Teff[ii] = T[0, ii] * (
                        Ki / Ke
                    )**0.5  # [s] effctive fundamental period of building.

                    ttime = timer() - time_o
                    print(f'Elapsed Time {round(ttime/60,2)} [m]')

                    plt.figure()
                    plt.plot(results2[:, 0], results2[:, 1])
                    plt.grid()

                    print('The mode shape is:')
                    print(MdeShape)

    return (results1, results2), (dtg1, dtg2), (tgfactor1,
                                                tgfactor2), (tgfactor1 * dtg1,
                                                             tgfactor2 * dtg2)
Example #5
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("==========================")
OPSDMOD.SuperDeadLoadGen(NbaysX[0], NbaysZ, NStr[0], XbayL, ZbayL, Qsd)
OPSDMOD.LiveLoadGen(NbaysX[0], NbaysZ, NStr[0], XbayL, ZbayL, Ql, Qlr)

# GRAVITY-LOADS-CASE ANALYSIS.
# ============================
ops.system('ProfileSPD')
ops.constraints('Transformation')
ops.numberer('RCM')
ops.test('NormDispIncr', 1.0e-4, 100)
ops.algorithm('KrylovNewton')
ops.integrator('LoadControl', 1)
ops.analysis('Static')
ops.analyze(1)
# Vertical reactions Calculation for verification.
# ------------------------------------------------
ops.reactions()
YReact = 0
for i in range((NbaysX[0] + 1) * (NbaysZ + 1)):
    if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'):
        YReact += ops.nodeReaction(99000 + i + 1, 2)
    else:
        YReact += ops.nodeReaction(i + 1, 2)
print('>>> Gravity loads applied...')

# ==========================================================================
# MODAL ANALYSIS FOR DETERMINING FUNDAMENTAL PERIOD AND ITS DIRECTION.
# ==========================================================================
(Tver, Tmaxver, Mast) = OPSDAN.ModalAnalysis(NStr[0], B, L, Wx, flex)

import ASCE716SSI as SSI
if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'):
Example #7
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
Example #8
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
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
Example #10
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
Example #11
0
print("Finished creating loading object...")

#----------------------------------------------------------
#  create the analysis
#----------------------------------------------------------
op.integrator('LoadControl', 0.05)
op.numberer('RCM')
op.system('SparseGeneral')
op.constraints('Transformation')
op.test('NormDispIncr', 1e-5, 20, 1)
op.algorithm('Newton')
op.analysis('Static')

print("Starting Load Application...")
op.analyze(201)

print("Load Application finished...")
#print("Loading Analysis execution time: [expr $endT-$startT] seconds.")

#op.wipe

op.reactions()
Nodereactions = dict()
Nodedisplacements = dict()
for i in range(201, nodeTag + 1):
    Nodereactions[i] = op.nodeReaction(i)
    Nodedisplacements[i] = op.nodeDisp(i)
print('Node Reactions are: ', Nodereactions)
print('Node Displacements are: ', Nodedisplacements)