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
示例#2
0
    def buildModel(K, periodStruct, dampRatio):

        wn = 2.0 * PI / periodStruct
        m = K / (wn * wn)

        ops.wipe()
        ops.model('basic', '-ndm', 1, '-ndf', 1)

        ops.node(1, 0.)
        ops.node(2, 0., '-mass', m)

        ops.uniaxialMaterial('Elastic', 1, K)
        ops.element('zeroLength', 1, 1, 2, '-mat', 1, '-dir', 1)
        ops.fix(1, 1)

        # add damping using rayleigh damping on the mass term
        a0 = 2.0 * wn * dampRatio
        ops.rayleigh(a0, 0., 0., 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
示例#4
0
文件: col_dim1.py 项目: ItaloIF/PFEM
# condiciones de frontera
boundFix(nNode, Node)

# fuerza dinamica
ti = 0 * s
tf = 0.2 * s
fr = 10 * Hz
prd = 1 / fr
ops.timeSeries('Trig', 1, ti, tf, prd)
# https://openseespydoc.readthedocs.io/en/latest/src/pathTs.html
ops.pattern('UniformExcitation', 1, 1, '-accel', 1)
# https://openseespydoc.readthedocs.io/en/latest/src/uniformExcitation.html

# amortiguamiento de rayleigh
ops.rayleigh(*setRayParam(0.05, 0.05, 0.2, 20))

# analysis commands
ops.constraints('Plain')
ops.numberer('Plain')
ops.system('UmfPack')
ops.algorithm('Linear')
ops.integrator('Newmark', 0.5, 0.25)
ops.analysis('Transient')

# analisis
# ops.analyze(400,0.001)
ops.start()
for i in range(400):
    ops.analyze(1, 0.001)
    print(i)
    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
示例#6
0
import InelasticFiberSection
#applying Dynamic Ground motion analysis
Tol = 1e-8
GMdirection = 1
GMfile = 'BM68elc.acc'
GMfact = 1.0
Lambda = op.eigen('-fullGenLapack', 1)  # eigenvalue mode 1
Omega = math.pow(Lambda, 0.5)
betaKcomm = 2 * (0.02 / Omega)

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

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

# Uniform EXCITATION: acceleration input
IDloadTag = 400  # load tag
dt = 0.01  # time step for input ground motion
GMfatt = 1.0  # data in input file is in g Unifts -- ACCELERATION TH
maxNumIter = 10
op.timeSeries('Path', 2, '-dt', dt, '-filePath', GMfile, '-factor', GMfact)
op.pattern('UniformExcitation', IDloadTag, GMdirection, '-accel', 2)

op.wipeAnalysis()
op.constraints('Transformation')
op.numberer('Plain')
op.system('BandGeneral')
op.test('EnergyIncr', Tol, maxNumIter)
op.algorithm('ModifiedNewton')
# Set some parameters
record = 'elCentro'

# 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
示例#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
示例#9
0
def build_model(model_params):
    """
    Generates OpenSeesPy model of an elastic cantilever and runs gravity analysis.

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

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

    """

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

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

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

    psf = 1.0
    Nsm = 4.88242  # N per square meter

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

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

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

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

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

    else:
        C_t = 0.02
        x = 0.75

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

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

    if 'length' in units.keys():

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

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

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

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

    m = W / G

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

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

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

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

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

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

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

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

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

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

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

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

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

    # after gravity analysis, change time and tolerance for the dynamic analysis
    ops.loadConst('-time', 0.0)
示例#10
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
示例#11
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("========================================")
示例#12
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("=========================================")
    KcurrSwitch = 1.0

    KcommSwitch = 0.0
    KinitSwitch = 0.0

    lambdaI = 3.8846291886219655
    lambdaJ = 64.78437186628662
    omegaI = pow(lambdaI, 0.5)
    omegaJ = pow(lambdaJ, 0.5)

    alphaM = MpropSwitch * xDamp * (2 * omegaI * omegaJ) / (omegaI + omegaJ)
    betaKcurr = KcurrSwitch * 2 * xDamp / (omegaI + omegaJ)
    betaKcomm = KcommSwitch * 2 * xDamp / (omegaI + omegaJ)
    betaKinit = KinitSwitch * 2 * xDamp / (omegaI + omegaJ)

    ops.rayleigh(alphaM, betaKcurr, betaKinit, betaKcomm)

    print("\n已创建rayleigh")
    # =============================================================================
    # clear all Analysis object
    # =============================================================================
    ops.wipeAnalysis()
    # =============================================================================
    # create timeSeries
    # =============================================================================

    IDloadTag = 1001
    iGMfile = pd.read_csv("GMX.txt", header=None)
    iGMdirection = 1
    iGMfact = "210*10"
    dt = 0.01
示例#14
0
def run_nlth_analysis_on_sdof_ops_py(capacity_curve, gmr, damping,
                                     degradation):

    cap_df = pd.DataFrame(capacity_curve)
    if any(cap_df.duplicated()):
        warnings.warn(
            "Warning: Duplicated pairs have been found in capacity curve!")

    ops.wipe()
    ops.model('basic', '-ndm', 1, '-ndf', 1)

    d_cap = capacity_curve[:, 0]
    f_cap = capacity_curve[:, 1] * 9.81

    f_vec = np.zeros([5, 1])
    d_vec = np.zeros([5, 1])
    if len(f_cap) == 3:
        #bilinear curve
        f_vec[1] = f_cap[1]
        f_vec[4] = f_cap[-1]

        d_vec[1] = d_cap[1]
        d_vec[4] = d_cap[-1]

        d_vec[2] = d_vec[1] + (d_vec[4] - d_vec[1]) / 3
        d_vec[3] = d_vec[1] + 2 * ((d_vec[4] - d_vec[1]) / 3)

        f_vec[2] = np.interp(d_vec[2], d_cap, f_cap)
        f_vec[3] = np.interp(d_vec[3], d_cap, f_cap)

    elif len(f_cap) == 4:

        f_vec[1] = f_cap[1]
        f_vec[4] = f_cap[-1]

        d_vec[1] = d_cap[1]
        d_vec[4] = d_cap[-1]

        f_vec[2] = f_cap[2]
        d_vec[2] = d_cap[2]

        d_vec[3] = np.mean([d_vec[2], d_vec[-1]])
        f_vec[3] = np.interp(d_vec[3], d_cap, f_cap)

    elif len(f_cap) == 5:
        f_vec[1] = f_cap[1]
        f_vec[4] = f_cap[-1]

        d_vec[1] = d_cap[1]
        d_vec[4] = d_cap[-1]

        f_vec[2] = f_cap[2]
        d_vec[2] = d_cap[2]

        f_vec[3] = f_cap[3]
        d_vec[3] = d_cap[3]

    matTag_pinching = 10
    if degradation == True:
        matargs = [
            f_vec[1, 0], d_vec[1, 0], f_vec[2, 0], d_vec[2, 0], f_vec[3, 0],
            d_vec[3, 0], f_vec[4, 0], d_vec[4, 0], -1 * f_vec[1, 0],
            -1 * d_vec[1, 0], -1 * f_vec[2, 0], -1 * d_vec[2, 0],
            -1 * f_vec[3, 0], -1 * d_vec[3, 0], -1 * f_vec[4, 0],
            -1 * d_vec[4, 0], 0.5, 0.25, 0.05, 0.5, 0.25, 0.05, 0, 0.1, 0, 0,
            0.2, 0, 0.1, 0, 0, 0.2, 0, 0.4, 0, 0.4, 0.9, 10, 'energy'
        ]

    else:
        matargs = [
            f_vec[1, 0], d_vec[1, 0], f_vec[2, 0], d_vec[2, 0], f_vec[3, 0],
            d_vec[3, 0], f_vec[4, 0], d_vec[4, 0], -1 * f_vec[1, 0],
            -1 * d_vec[1, 0], -1 * f_vec[2, 0], -1 * d_vec[2, 0],
            -1 * f_vec[3, 0], -1 * d_vec[3, 0], -1 * f_vec[4, 0],
            -1 * d_vec[4, 0], 0.5, 0.25, 0.05, 0.5, 0.25, 0.05, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'energy'
        ]

    ops.uniaxialMaterial('Pinching4', matTag_pinching, *matargs)
    matTag_minmax = int(matTag_pinching / 10)
    ops.uniaxialMaterial('MinMax', matTag_minmax, matTag_pinching, '-min',
                         -1 * d_vec[4, 0], '-max', d_vec[4, 0])

    mx = 1
    kx = f_vec[1, 0] / d_vec[1, 0]
    omega = np.sqrt(kx / mx)
    dt = gmr[1, 0] - gmr[0, 0]

    ops.node(1, 0)
    ops.node(2, 0, '-mass', float(mx))
    ops.fix(1, 1)
    ops.element('zeroLength', 1, 1, 2, "-mat", matTag_minmax, "-dir", 1,
                '-doRayleigh', 1)

    gmr_values = gmr[:, 1] * 9.81
    gmr_times = gmr[:, 0]
    ops.timeSeries('Path', 2, '-values', *gmr_values, '-time', *gmr_times)
    ops.pattern('UniformExcitation', 2, 1, '-accel', 2)

    ops.constraints('Plain')
    ops.numberer('RCM')
    ops.test('NormDispIncr', 1e-6, 50)
    ops.algorithm('Newton')
    ops.system('BandGeneral')
    ops.integrator('Newmark', 0.5, 0.25)
    ops.analysis('Transient')

    t_final = gmr[-1, 0]
    t_current = ops.getTime()
    ok = 0
    #betaKinit=2*damping/omega
    alphaM = 2 * damping * omega
    time = [t_current]
    disps = [0.0]
    accels = [0.0]
    #ops.rayleigh(0,0,betaKinit,0)
    ops.rayleigh(alphaM, 0, 0, 0)  # mass proportional damping
    while ok == 0 and t_current < t_final:
        ok = ops.analyze(1, dt)
        if ok != 0:
            print(
                "regular newton failed ... lets try an initail stiffness for this step"
            )
            ops.test('NormDispIncr', 1.0e-6, 100, 0)
            ops.algorithm('ModifiedNewton', '-initial')
            ok = ops.analyze(1, dt)
            if ok != 0:
                print("reducing dt by 10")
                ndt = dt / 10
                ok = ops.analyze(10, ndt)
            if ok == 0:
                print("that worked ... back to regular settings")
                ops.test('NormDispIncr', 1e-6, 50)
                ops.test('NormDispIncr', 1e-6, 50)
        t_current = ops.getTime()
        time.append(t_current)
        disps.append(ops.nodeDisp(2, 1))
        accels.append(ops.nodeAccel(2, 1))

    if ok != 0:
        print('NLTHA did not converge!')

    return time, disps, accels
示例#15
0
op.integrator('LoadControl', 0.1)
op.analysis('Static')
op.analyze(10)
    
op.loadConst('-time', 0.0)

#applying Dynamic Ground motion analysis
op.timeSeries('Path', 2, '-dt', 0.01, '-filePath', 'BM68elc.acc', '-factor', 1.0)
op.pattern('UniformExcitation', 2, 1, '-accel', 2) #how to give accelseriesTag?

eigen = op. eigen('-fullGenLapack', 1)
import math
power = math.pow(eigen, 0.5)
betaKcomm = 2 * (0.02/power)

op.rayleigh(0.0, 0.0, 0.0, betaKcomm)

op.wipeAnalysis()
op.constraints('Plain')
op.numberer('Plain')
op.system('BandGeneral')
op.test('NormDispIncr', 1e-8, 10)
op.algorithm('Newton')
op.integrator('Newmark', 0.5, 0.25)
op.analysis('Transient')
op.analyze(1000, 0.02)

u3 = op.nodeDisp(3, 1)
print("u2 = ", u3)

op.wipe()