예제 #1
0
    def write_input_files(self, N_batches=1):
        'Write ABAQUS input files and batch script(s)'

        # Open list of batch files
        batchfiles = []
        for b in range(N_batches):
            fname = '{0:s}/_run_{1:d}.bat'.format(self.out_dir, b)
            batchfiles.append(open(fname, 'w'))

        pp_script = open('{0:s}/_postproc.bat'.format(self.out_dir), 'w')

        b = 0
        for jobname, j in self.db.iterrows():
            w = self.wheel_from_row(j)
            mm = ModeMatrix(w)

            # Apply tension
            if j['spk_T'] == 0.:
                w.apply_tension(0.001)
            else:
                w.apply_tension(j['spk_T'])

            # Choose total radial displacement
            if j['sim_u2'] == 'auto':
                # Estimate radial displacement to failure for truss wheel
                Pc_est = mm.calc_lat_stiff() * w.rim.radius
                u_rad = 1.5 * Pc_est / mm.calc_rad_stiff()
            else:
                u_rad = j['sim_u2']

            # Write ABAQUS input files
            write_abaqus_pre(self.out_dir + '/' + jobname + '_preT.inp', w, j)
            write_abaqus_exp(self.out_dir + '/' + jobname + '_collapse.inp', w,
                             j, u_rad)

            # Write to batch file
            bf = batchfiles[b]
            bf.write('call abaqus interactive ')
            bf.write('job={0:s}_preT input={0:s}_preT.inp\n'.format(jobname))

            bf.write('call abaqus interactive ')
            bf.write(
                'job={0:s}_collapse input={0:s}_collapse.inp oldjob={0:s}_preT\n'
                .format(jobname))

            # Next batchfile
            b = (b + 1) % N_batches

            # Write entry to postprocess script
            pp_script.write('call abaqus python postproc_rad_buckling.py ' +
                            '{0:s}_collapse.odb\n'.format(jobname))

        # Close batch files
        for f in batchfiles:
            f.close()
예제 #2
0
def calc_tor_stiff(wheel,
                   theta=0.,
                   N=20,
                   smeared_spokes=True,
                   tension=True,
                   buckling=True,
                   coupling=True,
                   r0=False):
    'Calculate torsional (wind-up) stiffness in [N/rad].'

    mm = ModeMatrix(wheel, N=N)

    F_ext = mm.F_ext(theta, [0., 0., 1., 0.])
    d = np.zeros(F_ext.shape)

    K = (mm.K_rim(tension=buckling, r0=r0) +
         mm.K_spk(tension=tension, smeared_spokes=smeared_spokes))

    if coupling:
        d = np.linalg.solve(K, F_ext)
    else:
        ix_uc = mm.get_ix_uncoupled(dim='radial')
        K = mm.get_K_uncoupled(K=K, dim='radial')
        d[ix_uc] = np.linalg.solve(K, F_ext[ix_uc])

    return wheel.rim.radius / mm.B_theta(theta).dot(d)[2]
예제 #3
0
def calc_lat_stiff(wheel,
                   theta=0.,
                   N=20,
                   smeared_spokes=True,
                   tension=True,
                   buckling=True,
                   coupling=False,
                   r0=False):
    'Calculate lateral stiffness.'

    mm = ModeMatrix(wheel, N=N)

    F_ext = mm.F_ext(0., [1., 0., 0., 0.])
    d = np.zeros(F_ext.shape)

    K = (mm.K_rim(tension=buckling, r0=r0) +
         mm.K_spk(tension=tension, smeared_spokes=smeared_spokes))

    if coupling:
        d = np.linalg.solve(K, F_ext)
    else:
        ix_uc = mm.get_ix_uncoupled(dim='lateral')
        K = mm.get_K_uncoupled(K=K, dim='lateral')
        d[ix_uc] = np.linalg.solve(K, F_ext[ix_uc])

    return 1. / mm.B_theta(0.).dot(d)[0]
예제 #4
0
def calc_buckling_tension_modematrix(smeared_spokes=True,
                                     coupling=True,
                                     r0=True):
    'Estimate buckling tension from condition number of stiffness matrix.'

    mm = ModeMatrix(wheel, N=N)

    def neg_cond(T):
        wheel.apply_tension(T)

        K = (mm.K_rim(buckling=True, r0=r0) +
             mm.K_spk(smeared_spokes=smeared_spokes))

        if not coupling:
            K = mm.get_K_uncoupled(buckling=True,
                                   smeared_spokes=smeared_spokes)

        return -np.linalg.cond(K)

    # Find approximate buckling tension from linear analytical solution
    Tc_approx = calc_buckling_tension(wheel, approx='linear')

    # Maximize the condition number as a function of tension
    res = minimize(fun=neg_cond,
                   x0=[Tc_approx],
                   method='Nelder-Mead',
                   options={'maxiter': 50})

    return res.x[0]
예제 #5
0
    def extract_results(self):
        'Extract results and calculated quantities from ABAQUS output'

        def spoke_buckle_load(pd_data):
            'Get load at which spokes start to buckle'

            return pd_data.RF3[np.nonzero(pd_data.n_buckled)[0][0]]

        for i in self.db.index:
            print('.', end='')

            j = self.db.loc[i]
            w = self.wheel_from_row(j)
            mm = ModeMatrix(w)

            try:
                # Buckling tension
                Tc, nc = calc_buckling_tension(w)
                self.db.at[i, 'Tc'] = Tc
                self.db.at[i, 'nc'] = nc

                # Get load-deflection data
                if j['sim_type'] == 'exp':
                    pd_fname = self.out_dir + '/' + j.name + '_collapse_Pd.csv'
                elif j['sim_type'] == 'riks':
                    pd_fname = self.out_dir + '/' + j.name + '_riks_Pd.csv'

                pd_data = pd.read_csv(pd_fname)
                pd_data.columns = ['Time', 'U3', 'RF3', 'n_buckled']

                # Stiffness
                w.apply_tension(0.01)
                K_lat_0 = mm.calc_lat_stiff(smeared_spokes=True,
                                            coupling=False)
                K_rad_0 = mm.calc_rad_stiff(smeared_spokes=False,
                                            coupling=False)

                self.db.at[i, 'K_lat_0'] = K_lat_0
                self.db.at[i, 'K_rad_0'] = K_rad_0

                # Critical loads
                self.db.at[i, 'Pc_max'] = max(pd_data.RF3)
                self.db.at[i, 'Pc_spk'] = spoke_buckle_load(pd_data)

            except Exception as e:
                print('Error on {0:s}: {1:s}'.format(j.name, str(e)))
                continue
예제 #6
0
def calc_tor_stiff(wheel, theta=0., N=20, smeared_spokes=True, tension=True, buckling=True, coupling=True, r0=False):
    'Calculate torsional (wind-up) stiffness in [N/rad].'

    mm = ModeMatrix(wheel, N=N)

    F_ext = mm.F_ext(theta, [0., 0., 1., 0.])
    d = np.zeros(F_ext.shape)

    K = (mm.K_rim(tension=buckling, r0=r0) +
         mm.K_spk(tension=tension, smeared_spokes=smeared_spokes))

    if coupling:
        d = np.linalg.solve(K, F_ext)
    else:
        ix_uc = mm.get_ix_uncoupled(dim='radial')
        K = mm.get_K_uncoupled(K=K, dim='radial')
        d[ix_uc] = np.linalg.solve(K, F_ext[ix_uc])

    return wheel.rim.radius / mm.B_theta(theta).dot(d)[2]
예제 #7
0
def calc_lat_stiff(wheel, theta=0., N=20, smeared_spokes=True, tension=True, buckling=True, coupling=False, r0=False):
    'Calculate lateral stiffness.'

    mm = ModeMatrix(wheel, N=N)

    F_ext = mm.F_ext(0., [1., 0., 0., 0.])
    d = np.zeros(F_ext.shape)

    K = (mm.K_rim(tension=buckling, r0=r0) +
         mm.K_spk(tension=tension, smeared_spokes=smeared_spokes))

    if coupling:
        d = np.linalg.solve(K, F_ext)
    else:
        ix_uc = mm.get_ix_uncoupled(dim='lateral')
        K = mm.get_K_uncoupled(K=K, dim='lateral')
        d[ix_uc] = np.linalg.solve(K, F_ext[ix_uc])

    return 1. / mm.B_theta(0.).dot(d)[0]
예제 #8
0
def calc_buckling_tension_modematrix(wheel, smeared_spokes=False, coupling=True, r0=True, N=24):
    'Estimate buckling tension from condition number of stiffness matrix.'

    mm = ModeMatrix(wheel, N=N)

    K_matl = (mm.K_rim_matl(r0=r0) +
              mm.K_spk(tension=False, smeared_spokes=smeared_spokes))

    K_geom = (mm.K_rim_geom(r0=r0) -
              mm.K_spk_geom(smeared_spokes=smeared_spokes))

    # Solve generalized eigienvalue problem:
    #   (K_matl + T*K_geom)
    if coupling:
        w, v = eig(K_matl, K_geom)
    else:
        w, v = eig(mm.get_K_uncoupled(K_matl),
                   mm.get_K_uncoupled(K_geom))

    return np.min(np.real(w)[np.real(w) > 0])
예제 #9
0
def calc_rad_stiff(wheel):
    'Calculate radial stiffness.'

    # Create a ModeMatrix model with 24 modes
    mm = ModeMatrix(wheel, N=24)

    # Calculate stiffness matrix
    K = mm.K_rim(tension=True) + mm.K_spk(smeared_spokes=False, tension=True)

    # Create a unit radial load pointing radially inwards at theta=0
    F_ext = mm.F_ext(0., np.array([0., 1., 0., 0.]))

    # Solve for the mode coefficients
    dm = np.linalg.solve(K, F_ext)

    return 1e-6 / mm.rim_def_rad(0., dm)[0]
예제 #10
0
def calc_rot_stiff(wheel):
    'Calculate rotational (wind-up) stiffness.'

    # Create a ModeMatrix model with 24 modes
    mm = ModeMatrix(wheel, N=24)

    # Calculate stiffness matrix
    K = mm.K_rim(tension=True) + mm.K_spk(smeared_spokes=False, tension=True)

    # Create a unit tangential load at theta=0
    F_ext = mm.F_ext(0., np.array([0., 0., 1., 0.]))

    # Solve for the mode coefficients
    dm = np.linalg.solve(K, F_ext)

    return 1e-3*np.pi/180*wheel.rim.radius / mm.rim_def_tan(0., dm)[0]
예제 #11
0
def calc_lat_stiff(wheel):
    'Calculate lateral (side-load) stiffness.'

    # Create a ModeMatrix model with 24 modes
    mm = ModeMatrix(wheel, N=24)

    # Calculate stiffness matrix
    K = mm.K_rim(tension=True) + mm.K_spk(smeared_spokes=False, tension=True)

    # Create a unit lateral load at theta=0
    F_ext = mm.F_ext(0., np.array([1., 0., 0., 0.]))

    # Solve for the mode coefficients
    dm = np.linalg.solve(K, F_ext)

    return 1e-3 / mm.rim_def_lat(0., dm)[0]
예제 #12
0
def calc_buckling_tension_modematrix(wheel,
                                     smeared_spokes=False,
                                     coupling=True,
                                     r0=True,
                                     N=24):
    'Estimate buckling tension from condition number of stiffness matrix.'

    mm = ModeMatrix(wheel, N=N)

    K_matl = (mm.K_rim_matl(r0=r0) +
              mm.K_spk(tension=False, smeared_spokes=smeared_spokes))

    K_geom = (mm.K_rim_geom(r0=r0) -
              mm.K_spk_geom(smeared_spokes=smeared_spokes))

    # Solve generalized eigienvalue problem:
    #   (K_matl + T*K_geom)
    if coupling:
        w, v = eig(K_matl, K_geom)
    else:
        w, v = eig(mm.get_K_uncoupled(K_matl), mm.get_K_uncoupled(K_geom))

    return np.min(np.real(w)[np.real(w) > 0])
예제 #13
0
# Create an example wheel and rim
wheel = BicycleWheel()
wheel.hub = Hub(width=0.05, diameter=0.05)
wheel.rim = Rim(radius=0.3,
                area=100e-6,
                I_lat=200. / 69e9,
                I_rad=100. / 69e9,
                J_tor=25. / 26e9,
                I_warp=0.0,
                young_mod=69e9,
                shear_mod=26e9)
wheel.lace_cross(n_spokes=36, n_cross=3, diameter=2.0e-3, young_mod=210e9)

# Create a ModeMatrix model with 24 modes
mm = ModeMatrix(wheel, N=24)

# Create a 500 Newton pointing radially inwards at theta=0
F_ext = mm.F_ext(0., np.array([0., 500., 0., 0.]))

# Calculate stiffness matrix
K = mm.K_rim(tension=False) + mm.K_spk(smeared_spokes=False, tension=False)

# Solve for the mode coefficients
dm = np.linalg.solve(K, F_ext)

# Get radial deflection
theta = np.linspace(-np.pi, np.pi, 100)
rad_def = mm.rim_def_rad(theta, dm)

# Calculate change in spoke tensions
wheel.hub = Hub(diameter=0.050, width=0.05)
wheel.rim = Rim(radius=0.3, area=100e-6,
                I_lat=200./69e9, I_rad=100./69e9, J_tor=25./26e9, I_warp=0.0,
                young_mod=69e9, shear_mod=26e9)

diam_flange = np.linspace(0.01, 0.1, 10)
rot_stiff = []

for d in diam_flange:

    # Create hub and spokes for each flange diameter
    wheel.hub = Hub(width=0.025, diameter=d)
    wheel.lace_cross(n_spokes=36, n_cross=3, diameter=2.0e-3, young_mod=210e9)

    # Create a ModeMatrix model with 24 modes
    mm = ModeMatrix(wheel, N=24)

    # Create a unit tangential force
    F_ext = mm.F_ext(0., np.array([0., 0., 1., 0.]))

    # Calculate stiffness matrix
    K = mm.K_rim(tension=False) + mm.K_spk(smeared_spokes=True, tension=False)

    # Solve for the mode coefficients
    dm = np.linalg.solve(K, F_ext)

    # Calculate the rotational stiffness
    rot_stiff.append(np.pi/180*wheel.rim.radius/mm.rim_def_tan(0., dm)[0])

plt.plot(diam_flange * 100, rot_stiff, 'ro')
plt.xlabel('Flange diameter [cm]')
from bikewheelcalc import BicycleWheel, Rim, Hub, ModeMatrix
import matplotlib.pyplot as plt
import numpy as np


# Create an example wheel and rim
wheel = BicycleWheel()
wheel.hub = Hub(width=0.05, diameter=0.05)
wheel.rim = Rim(radius=0.3, area=100e-6,
                I_lat=200./69e9, I_rad=100./69e9, J_tor=25./26e9, I_warp=0.0,
                young_mod=69e9, shear_mod=26e9)
wheel.lace_cross(n_spokes=36, n_cross=3, diameter=2.0e-3, young_mod=210e9)


# Create a ModeMatrix model with 24 modes
mm = ModeMatrix(wheel, N=24)

# Create a 500 Newton pointing radially inwards at theta=0
F_ext = mm.F_ext(0., np.array([0., 500., 0., 0.]))

# Calculate stiffness matrix
K = mm.K_rim(tension=False) + mm.K_spk(smeared_spokes=False, tension=False)

# Solve for the mode coefficients
dm = np.linalg.solve(K, F_ext)

# Get radial deflection
theta = np.linspace(-np.pi, np.pi, 100)
rad_def = mm.rim_def_rad(theta, dm)

# Calculate change in spoke tensions
예제 #16
0
    def extract_results(self):
        'Extract results and calculated quantities from ABAQUS output'

        def buckling_load_southwell(pd_data):
            'Get critical buckling load from Southwell plot'
            pass

        def buckling_load_nonlin(pd_data):
            'Get critical buckling from departure from linearity'

            # Fit straight line to first 5% of data
            N = int(np.ceil(0.05 * len(pd_data)))
            pf = np.polyfit(pd_data['U2'][:N], pd_data['RF2'][:N], 1)

            err = (np.polyval(pf, pd_data['U2']) - pd_data['RF2']) /\
                np.mean(pd_data['RF2'])
            return pd_data['RF2'][np.argmax(np.abs(err) > 0.02)]

        def calc_T_nb(w, K_lat_0, K_rad_0, Tc, form=1):
            'Calculate minimum spoke tension for no spoke buckling'

            R = w.rim.radius
            EA = w.spokes[0].EA
            alpha = w.spokes[0].alpha
            ls = w.spokes[0].length

            if form == 2:
                # Quadratic approximation for K_lat(T)
                x = K_rad_0 * Tc * ls / (2 * EA * K_lat_0 * R * np.cos(alpha))
                return np.sqrt(1 + x**2) - x
            else:
                # Linear approximation for K_lat(T)
                return 1.0 / (1 + K_rad_0 * ls * Tc /
                              (K_lat_0 * R * EA * np.cos(alpha)))

        def calc_P_nb(w, K_lat_0, K_rad_0, Tc, form=1):
            'Critical load at the critical no-buckling tension'

            R = w.rim.radius
            EA = w.spokes[0].EA
            alpha = w.spokes[0].alpha
            ls = w.spokes[0].length

            if form == 2:
                # Quadratic approximation for K_lat(T)
                x = K_rad_0 * Tc * ls / (2 * EA * K_lat_0 * R * np.cos(alpha))
                T_nb = np.sqrt(1 + x**2) - x
                return K_lat_0 * R * (1 - T_nb**2)
            else:
                # Linear approximation for K_lat(T)
                return K_lat_0 * R / (1 + EA / Tc * K_lat_0 / K_rad_0)

        for i in self.db.index:
            print('.', end='')

            j = self.db.loc[i]
            w = self.wheel_from_row(j)
            mm = ModeMatrix(w)

            try:
                # Buckling tension
                Tc, nc = calc_buckling_tension(w)
                self.db.at[i, 'Tc'] = Tc
                self.db.at[i, 'nc'] = nc

                # Get load-deflection data
                pd_data = pd.read_csv(self.out_dir + '/' + j.name +
                                      '_collapse_Pd.csv')
                pd_data.columns = ['Time', 'U2', 'RF2', 'U3', 'n_buckled']

                # Stiffness at zero tension
                w.apply_tension(0.01)
                K_lat_0 = mm.calc_lat_stiff(smeared_spokes=True,
                                            coupling=False)
                K_rad_0 = mm.calc_rad_stiff(smeared_spokes=False,
                                            coupling=False)

                w.apply_tension(j['spk_T'])
                K_lat = mm.calc_lat_stiff(smeared_spokes=True, coupling=False)

                self.db.at[i, 'K_lat_0'] = K_lat_0
                self.db.at[i, 'K_rad_0'] = K_rad_0
                self.db.at[i, 'K_lat'] = K_lat

                # Radial buckling load
                self.db.at[i, 'Pc_max'] = max(pd_data.RF2)
                self.db.at[i, 'Pc_nonlin'] = buckling_load_nonlin(pd_data)

                self.db.at[i, 'T_nb'] = calc_T_nb(w, K_lat_0, K_rad_0, Tc)
                self.db.at[i, 'Pc_nb'] = calc_P_nb(w, K_lat_0, K_rad_0, Tc)
                self.db.at[i, 'T_nb_2'] = calc_T_nb(w,
                                                    K_lat_0,
                                                    K_rad_0,
                                                    Tc,
                                                    form=2)
                self.db.at[i, 'Pc_nb_2'] = calc_P_nb(w,
                                                     K_lat_0,
                                                     K_rad_0,
                                                     Tc,
                                                     form=2)

            except Exception as e:
                print('Error on {0:s}: {1:s}'.format(j.name, str(e)))
                continue