Exemplo n.º 1
0
    def test_undamped_2DOF(self, M1, M2, K1, K2):
        """
        Obtain angular natural frequencies for a 2 degree of freedom undamped 
        system as per the following sketch :
            
        ![2dof_undamped](../img/2dof_undamped.PNG)
        
        Expected results are obtained using the following equations, reproduced 
        from John Rees' (EJR, COWI UK Bridge) TMD lecture notes:
        [PDF](../ref/Lecture Notes - Damping and Tuned Mass Dampers (Rev. 0.7).pdf)
        
        ![angular_freq_eqns](../img/2dof_undamped_angularFreq.PNG)
        
        """

        # Create msd_chain system
        msd_sys = msd_chain.MSD_Chain(M_vals=[M1, M2],
                                      K_vals=[K1, K2],
                                      C_vals=[0, 0],
                                      showMsgs=False)

        # Obtain undamped natural frequencies
        w_n = msd_sys.CalcEigenproperties()["w_n"]

        # Note eigenvalues are in conjugate pairs
        w1 = numpy.abs(w_n[1])
        w2 = numpy.abs(w_n[3])

        # Implement equations presented in EJR's note
        w1_2_bar = K1 / (M1 + M2)
        w2_2_bar = K2 / M2
        mu = M2 / M1
        term1 = 0.5 * (w1_2_bar + w2_2_bar) * (1 + mu)
        term2 = 0.5 * (((w1_2_bar + w2_2_bar) *
                        (1 + mu))**2 - 4 * w1_2_bar * w2_2_bar * (1 + mu))**0.5
        w1_expected = (term1 - term2)**0.5
        w2_expected = (term1 + term2)**0.5

        # Check results agree
        self.assertAlmostEqual(w1, w1_expected)
        self.assertAlmostEqual(w2, w2_expected)
Exemplo n.º 2
0
def ResponseSpectrum(accFunc,
                     tResponse,
                     T_vals=None,
                     eta=0.05,
                     makePlot=True,
                     **kwargs):
    """
    Function to express ground acceleration time series as a seismic response 
    spectrum
    ***
    
    _Seismic response spectra_ are used to summarises the vibration response 
    of a SDOF oscillator in response to a transient ground acceleration 
    time series. Seismic response spectra therefore represent a useful way of 
    quantifying and graphically illustrating the severity of a given 
    ground acceleration time series.
    
    
    
    ***
    Required:
    
    * `accFunc`, function a(t) defining the ground acceleration time series 
      (usually this is most convenient to supply via an interpolation function)
      
    * `tResponse`, time interval over which to carry out time-stepping analysis.
      Set this to be at least the duration of the input acceleration time 
      series!
      
    **Important note**:
        
    This routine expects a(t) to have units of m/s<sup>2</sup>. 
    It is common (at least in the field of seismic analysis) to quote ground 
    accelerations in terms of 'g'.
    
    Any such time series must be pre-processed by multiplying by 
    g=9.81m/s<sup>2</sup>) prior to using this function, such that the 
    supplied `accFunc` returns ground acceleration in m/s<sup>2</sup>.
      
    ***
    Optional:
        
    * `T_vals`, _list_, periods (in seconds) at which response spectra
      are to be evaluated. If _None_ will be set to logarithmically span the range 
      [0.01,10.0] seconds, which is suitable for most applications.
        
    * `eta`, damping ratio to which response spectrum obtained is applicable. 
      5% is used by default, as this a common default in seismic design.
      
     * `makePlot`, _boolean_, controls whether results are plotted
      
     `kwargs` may be used to pass additional arguments down to `TStep` object 
     that is used to implement time-stepping analysis. Refer `tstep` docs for 
     further details
     
    ***
    Returns:
        
    Values are returned as a dictionary, containing the following entries:
        
    * `T_vals`, periods at which spectra are evaluated.
    * `S_D`, relative displacement spectrum (in m)
    * `S_V`, relative velocity spectrum (in m/s)
    * `S_A`, absolute acceleration spectrum (in m/s<sup>2</sup>)
    * `PSV`, psuedo-velocity spectrum (in m/s)
    * `PSA`, psuedo-acceleration spectrum (in m/s<sup>2</sup>)
    
    In addition, if `makePlot=True`:
        
    * `fig`, figure object for plot
    
    """
    
    # Handle optional inputs
    if T_vals is None:
        T_vals = numpy.logspace(-2,1,100)
        
    T_vals = numpy.ravel(T_vals).tolist()
    
    # Print summary of key inputs
    if hasattr(accFunc,"__name__"):
        print("Ground motion function supplied: %s" % accFunc.__name__)
    print("Time-stepping analysis interval: [%.2f, %.2f]" % (0,tResponse))
    print("Number of SDOF oscillators to be analysed: %d" % len(T_vals))
    print("Damping ratio for SDOF oscillators: {:.2%}".format(eta))
    
    # Loop through all periods
    M = 1.0 # unit mass for all oscillators
    results_list = []
    
    print("Obtaining SDOF responses to ground acceleration...")
    
    for i, _T in enumerate(T_vals):

        period_str = "Period %.2fs" % _T
        
        if i % 10 == 0:
            print("    Period %d of %d" % (i,len(T_vals)))
        
        # Define SDOF oscillator
        SDOF_sys = msd_chain.MSD_Chain(name=period_str,
                                       M_vals = M,
                                       f_vals = 1/_T,
                                       eta_vals = eta,
                                       showMsgs=False)
        
        # Add output matrix to extract results
        SDOF_sys.AddOutputMtrx(output_mtrx=numpy.identity(3),
                               output_names=["RelDisp","RelVel","Acc"])
        
        # Define forcing function
        def forceFunc(t):
            return -M*accFunc(t)
        
        # Define time-stepping analysis
        tstep_obj = tstep.TStep(SDOF_sys,
                                tStart=0, tEnd=tResponse,
                                force_func_dict={SDOF_sys:forceFunc},
                                retainResponseTimeSeries=True)
        
        # Run time-stepping analysis and append results
        results_obj = tstep_obj.run(verbose=False)
        results_list.append(results_obj)
        
        # Obtain absolute acceleration by adding back in ground motion
        results_obj.responses_list[0][2,:] += accFunc(results_obj.t.T)
        
        # Recalculate statistics
        results_obj.CalcResponseStats(verbose=False)
        
        # Tidy up
        del SDOF_sys
    
    # Collate absmax statistics
    print("Retrieving maximum response statistics...")
    S_D = numpy.asarray([x.response_stats['absmax'][0] for x in results_list])
    S_V = numpy.asarray([x.response_stats['absmax'][1] for x in results_list])
    S_A = numpy.asarray([x.response_stats['absmax'][2] for x in results_list])
    
    # Evaluate psuedo-specta
    omega = numpy.divide(2*numpy.pi,T_vals)
    PSV = omega * S_D
    PSA = omega**2 * S_D
    
    if makePlot:
        
        fig, axarr = plt.subplots(3, sharex=True)
        
        fig.suptitle("Response spectra: {:.0%} damping".format(eta))
        
        ax = axarr[0]
        ax.plot(T_vals,S_D)
        ax.set_ylabel("SD (m)")
        ax.set_title("Relative displacement")
        
        
        ax = axarr[1]
        ax.plot(T_vals,S_V)
        ax.plot(T_vals,PSV)
        ax.legend((ax.lines),("$S_V$","Psuedo $S_V$",),loc='upper right')
        ax.set_ylabel("SV (m/s)")
        ax.set_title("Relative velocity")
        
        ax = axarr[2]
        ax.plot(T_vals,S_A)
        ax.plot(T_vals,PSA)
        ax.legend((ax.lines),("$S_A$","Psuedo $S_A$",),loc='upper right')
        ax.set_ylabel("SA (m/$s^2$)")
        ax.set_title("Absolute acceleration")
        
        ax.set_xlim([0,numpy.max(T_vals)])
        ax.set_xlabel("Oscillator natural period T (secs)")
        
        fig.tight_layout()
        fig.subplots_adjust(top=0.90)
    
    # Return values as dict
    return_dict = {}
    return_dict["T_vals"]=T_vals
    
    return_dict["S_D"]=S_D
    return_dict["S_V"]=S_V
    return_dict["S_A"]=S_A
    
    return_dict["PSV"]=PSV
    return_dict["PSA"]=PSA
    
    if makePlot:
        return_dict["fig"]=fig
    else:
        return_dict["fig"]=None
    
    return return_dict
Exemplo n.º 3
0
# Overlay frequency transfer function for relative displacement
plot_dict = PlotFrequencyResponse(f2,
                                  G_f2[:, 2, 0],
                                  label_str="Relative disp (m)",
                                  ax_magnitude=plot_dict["ax_magnitude"],
                                  ax_phase=plot_dict["ax_phase"])

print("Max |G_f|, relative disp: %.2e" % numpy.max(numpy.abs(G_f2[:, 2, 0])))

plot_dict["ax_magnitude"].axvline(f_D, color='c', alpha=0.4)
plot_dict["ax_phase"].axvline(f_D, color='c', alpha=0.4)

#%%

# Obtain frequency response for main mass only
main_sys = msd_chain.MSD_Chain(M_vals=m_M, f_vals=f_M, eta_vals=gamma_M)

rslts = main_sys.CalcFreqResponse(fmax=fmax)
f3 = rslts['f']
G_f3 = rslts['G_f']

print("Max |G_f|, system with no TMDs: %.2e" %
      numpy.max(numpy.abs(G_f3[:, 0, 0])))

# Overlay to compare frequency response
PlotFrequencyResponse(f3,
                      G_f3[:, 0, 0],
                      label_str="using CalcFreqResponse(), no TMD",
                      ax_magnitude=plot_dict["ax_magnitude"],
                      ax_phase=plot_dict["ax_phase"])
Exemplo n.º 4
0
                  resultsproc_time)

        return results_obj


# ********************** FUNCTIONS *******************************************

# ********************** TEST ROUTINE ****************************************

if __name__ == "__main__":

    import msd_chain

    # Define dynamic system
    mySys = msd_chain.MSD_Chain([100, 50, 100, 50], [1.2, 1.8, 2.0, 4.5],
                                [0.03, 0.02, 0.01, 0.1],
                                isSparse=False)

    mySys.AddConstraintEqns(Jnew=[[1, -1, 0, 0], [0, 0, 1, -1]], Jkey="test")
    mySys.PrintSystemMatrices(printShapes=True, printValues=True)

    # Define output matrix to return relative displacements
    outputMtrx = npy.asmatrix([[1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                               [0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
    outputNames = ["Rel disp 12", "Rel disp 23"]
    mySys.AddOutputMtrx(output_mtrx=outputMtrx, output_names=outputNames)

    # Define applied forces
    def sine_force(t, F0, f):

        F0 = npy.asarray(F0)
Exemplo n.º 5
0
"""
Created on Fri Aug 10 19:32:48 2018

@author: whoever
"""

import numpy


import msd_chain
import tstep


# Define a very basic SDOF system
my_sys = msd_chain.MSD_Chain(M_vals=[1.0],
                             f_vals=[1.0],
                             eta_vals=[0.02])



def up_pass(t, y):
    return y[0]

def down_pass(t, y):
    
#    if t<3.0:
#        return 1.0 # no events
#    else:
#        return y[0]
    return y[0]-0.2