Пример #1
0
    def compute_applied_axial(self, params):
        """Compute axial stress for spar from z-axis loading

        INPUTS:
        ----------
        params       : dictionary of input parameters
        section_mass : float (scalar/vector),  mass of each spar section as axial loading increases with spar depth

        OUTPUTS:
        -------
        stress   : float (scalar/vector),  axial stress
        """
        # Unpack variables
        R_od, _ = nodal2sectional(params['d_full'])
        R_od *= 0.5
        t_wall, _ = nodal2sectional(params['t_full'])
        section_mass = params['section_mass']
        m_stack = params['stack_mass_in']

        # Middle radius
        R = R_od - 0.5 * t_wall
        # Add in weight of sections above it
        axial_load = m_stack + np.r_[0.0, np.cumsum(section_mass[:-1])]
        # Divide by shell cross sectional area to get stress
        return (gravity * axial_load / (2.0 * np.pi * R * t_wall))
Пример #2
0
    def solve_nonlinear(self, params, unknowns, resids):
        d,_ = nodal2sectional(params['d'])
        tube = Tube(d,params['t'])

        unknowns['Az'] = tube.Area
        unknowns['Asx'] = tube.Asx
        unknowns['Asy'] = tube.Asy
        unknowns['Jz'] = tube.J0
        unknowns['Ixx'] = tube.Jxx
        unknowns['Iyy'] = tube.Jyy
Пример #3
0
    def solve_nonlinear(self, params, unknowns, resids):
        d, _ = nodal2sectional(params['d'])
        tube = Tube(d, params['t'])

        unknowns['Az'] = tube.Area
        unknowns['Asx'] = tube.Asx
        unknowns['Asy'] = tube.Asy
        unknowns['Jz'] = tube.J0
        unknowns['Ixx'] = tube.Jxx
        unknowns['Iyy'] = tube.Jyy
Пример #4
0
    def solve_nonlinear(self, params, unknowns, resids):
        # Unpack some variables
        axial_stress = params['axial_stress']
        shear_stress = params['shear_stress']
        hoop_stress  = params['hoop_stress']
        sigma_y      = params['sigma_y'] * np.ones(axial_stress.shape)
        E            = params['E'] * np.ones(axial_stress.shape)
        L_reinforced = params['L_reinforced'] * np.ones(axial_stress.shape)
        d,_          = nodal2sectional(params['d'])
        z_section,_  = nodal2sectional(params['z'])

        # Frequencies
        unknowns['structural_frequencies'] = np.zeros(NFREQ)
        unknowns['structural_frequencies'][0] = params['f1']
        unknowns['structural_frequencies'][1] = params['f2']
        
        # von mises stress
        unknowns['stress'] = Util.vonMisesStressUtilization(axial_stress, hoop_stress, shear_stress,
                      params['gamma_f']*params['gamma_m']*params['gamma_n'], sigma_y)

        # shell buckling
        unknowns['shell_buckling'] = Util.shellBucklingEurocode(d, params['t'], axial_stress, hoop_stress,
                                                                shear_stress, L_reinforced, E, sigma_y, params['gamma_f'], params['gamma_b'])

        # global buckling
        tower_height = params['z'][-1] - params['z'][0]
        M = np.sqrt(params['Mxx']**2 + params['Myy']**2)
        unknowns['global_buckling'] = Util.bucklingGL(d, params['t'], params['Fz'], M, tower_height, E,
                                                      sigma_y, params['gamma_f'], params['gamma_b'])

        # fatigue
        N_DEL = 365.0*24.0*3600.0*params['life'] * np.ones(len(params['t']))
        unknowns['damage'] = np.zeros(N_DEL.shape)
        if any(params['M_DEL']):
            M_DEL = np.interp(z_section, params['z_DEL'], params['M_DEL'])

            unknowns['damage'] = Util.fatigue(M_DEL, N_DEL, d, params['t'], params['m_SN'],
                                              params['DC'], params['gamma_fatigue'], stress_factor=1.0, weld_factor=True)
Пример #5
0
    def setUp(self):
        self.params = {}
        self.unknowns = {}
        self.resid = None

        # For Geometry call
        self.params['z_full_in'] = np.linspace(0, 50.0, NPTS)
        self.params['z_param_in'] = np.array([0.0, 20.0, 50.0])
        self.params['section_height'] = np.array([20.0, 30.0])
        self.params['section_center_of_mass'], _ = nodal2sectional(
            self.params['z_full_in'])
        self.params['freeboard'] = 15.0
        self.params['fairlead'] = 10.0
        self.params['water_depth'] = 100.0

        self.params['t_full'] = 0.5 * myones
        self.params['d_full'] = 2 * 10.0 * myones

        self.params['stack_mass_in'] = 0.0

        self.params['shell_I_keel'] = 10.0 * np.array(
            [1.0, 1.0, 1.0, 0.0, 0.0, 0.0])
        self.params['stiffener_I_keel'] = 20.0 * np.array(
            [1.0, 1.0, 1.0, 0.0, 0.0, 0.0])
        self.params['bulkhead_I_keel'] = 30.0 * np.array(
            [1.0, 1.0, 1.0, 0.0, 0.0, 0.0])

        self.params['water_density'] = 1e3
        self.params['bulkhead_mass'] = 10.0 * myones
        self.params['shell_mass'] = 500.0 * np.ones(NPTS - 1)
        self.params['stiffener_mass'] = 100.0 * np.ones(NPTS - 1)
        self.params['column_mass_factor'] = 1.1
        self.params['outfitting_mass_fraction'] = 0.05

        self.params['permanent_ballast_height'] = 1.0
        self.params['permanent_ballast_density'] = 2e3

        self.params['mooring_mass'] = 50.0
        self.params['mooring_vertical_load'] = 25.0
        self.params['mooring_restoring_force'] = 1e5
        self.params['mooring_cost'] = 1e4

        self.params['ballast_cost_rate'] = 10.0
        self.params['tapered_col_cost_rate'] = 100.0
        self.params['outfitting_cost_rate'] = 1.0

        self.geom = column.ColumnGeometry(NSEC, NPTS)
        self.set_geometry()

        self.myspar = column.ColumnProperties(NPTS)
Пример #6
0
    def solve_nonlinear(self, params, unknowns, resids):
        # Unpack variables
        R_od, _ = nodal2sectional(params['d_full'])
        R_od *= 0.5
        h_section = np.diff(params['z_full'])
        t_wall, _ = nodal2sectional(params['t_full'])
        z_param = params['z_param']
        z_section = params['z_section']
        t_web = sectionalInterp(z_section, z_param,
                                params['stiffener_web_thickness'])
        t_flange = sectionalInterp(z_section, z_param,
                                   params['stiffener_flange_thickness'])
        h_web = sectionalInterp(z_section, z_param,
                                params['stiffener_web_height'])
        w_flange = sectionalInterp(z_section, z_param,
                                   params['stiffener_flange_width'])
        L_stiffener = sectionalInterp(z_section, z_param,
                                      params['stiffener_spacing'])
        E = params['E']  # Young's modulus
        nu = params['nu']  # Poisson ratio
        sigma_y = params['yield_stress']
        loading = params['loading']
        pressure, _ = nodal2sectional(params['pressure'])

        # Compute applied axial stress simply, like API guidelines (as opposed to running frame3dd)
        sigma_ax = self.compute_applied_axial(params)
        (flange_compactness, web_compactness, axial_local_unity,
         axial_general_unity, external_local_unity,
         external_general_unity) = shellBuckling_withStiffeners(
             pressure, sigma_ax, R_od, t_wall, h_section, h_web, t_web,
             w_flange, t_flange, L_stiffener, E, nu, sigma_y, loading)
        unknowns['flange_compactness'] = flange_compactness
        unknowns['web_compactness'] = web_compactness
        unknowns['axial_local_unity'] = axial_local_unity
        unknowns['axial_general_unity'] = axial_general_unity
        unknowns['external_local_unity'] = external_local_unity
        unknowns['external_general_unity'] = external_general_unity
Пример #7
0
    def setUp(self):
        self.params = {}
        self.unknowns = {}
        self.resid = None

        self.params['z_full_in'] = np.linspace(0, 50.0, NPTS)
        self.params['z_param_in'] = np.array([0.0, 20.0, 50.0])
        self.params['section_height'] = np.array([20.0, 30.0])
        self.params['section_center_of_mass'], _ = nodal2sectional(
            self.params['z_full_in'])
        self.params['freeboard'] = 15.0
        self.params['fairlead'] = 10.0
        self.params['water_depth'] = 100.0

        self.geom = column.ColumnGeometry(NSEC, NPTS)
Пример #8
0
    def solve_nonlinear(self, params, unknowns, resids):

        d,_ = nodal2sectional(params['d'])
        t = params['t']

        # Check if the input was radii instead of diameters and convert if necessary
        if not self.diamFlag: d *= 2.0
        
        min_d_to_t = params['min_d_to_t']
        max_taper = params['max_taper']

        unknowns['weldability'] = 1.0 - (d/t)/min_d_to_t
        d_ratio = d[1:]/d[:-1]
        manufacturability = np.minimum(d_ratio, 1.0/d_ratio) - max_taper
        unknowns['manufacturability'] = np.r_[manufacturability, manufacturability[-1]]
Пример #9
0
    def testRegular(self):
        # Straight column
        self.cm.solve_nonlinear(self.params, self.unknowns, self.resid)

        expect = np.pi*(10.**2 - 9.5**2)*5.0*1.5*(50.0/(npts-1))
        m = expect*(npts-1)
        Iax = 0.5*m*(10.**2 + 9.5**2)
        Ix = (1/12.)*m*(3*(10.**2 + 9.5**2) + 50*50) + m*25*25 # parallel axis on last term
        z_avg,_ = nodal2sectional(self.params['z_full'])
        self.assertAlmostEqual(self.unknowns['mass'].sum(), m)
        npt.assert_almost_equal(self.unknowns['mass'], expect)
        npt.assert_almost_equal(self.unknowns['section_center_of_mass'], z_avg)
        self.assertAlmostEqual(self.unknowns['center_of_mass'], 25.0)
        npt.assert_almost_equal(self.unknowns['I_base'], [Ix, Ix, Iax, 0.0, 0.0, 0.0], decimal=5)

        '''
Пример #10
0
    def solve_nonlinear(self, params, unknowns, resids):

        d, _ = nodal2sectional(params['d'])
        t = params['t']

        # Check if the input was radii instead of diameters and convert if necessary
        if not self.diamFlag: d *= 2.0

        min_d_to_t = params['min_d_to_t']
        max_taper = params['max_taper']

        unknowns['weldability'] = 1.0 - (d / t) / min_d_to_t
        d_ratio = d[1:] / d[:-1]
        manufacturability = np.minimum(d_ratio, 1.0 / d_ratio) - max_taper
        unknowns['manufacturability'] = np.r_[manufacturability,
                                              manufacturability[-1]]
Пример #11
0
    def testRegular(self):
        # Straight column
        self.cm.solve_nonlinear(self.params, self.unknowns, self.resid)

        expect = np.pi * (10.**2 - 9.5**2) * 5.0 * 1.5 * (50.0 / (npts - 1))
        m = expect * (npts - 1)
        Iax = 0.5 * m * (10.**2 + 9.5**2)
        Ix = (1 / 12.) * m * (3 * (10.**2 + 9.5**2) + 50 *
                              50) + m * 25 * 25  # parallel axis on last term
        z_avg, _ = nodal2sectional(self.params['z_full'])
        self.assertAlmostEqual(self.unknowns['mass'].sum(), m)
        npt.assert_almost_equal(self.unknowns['mass'], expect)
        npt.assert_almost_equal(self.unknowns['section_center_of_mass'], z_avg)
        self.assertAlmostEqual(self.unknowns['center_of_mass'], 25.0)
        npt.assert_almost_equal(self.unknowns['I_base'],
                                [Ix, Ix, Iax, 0.0, 0.0, 0.0],
                                decimal=5)
        '''
Пример #12
0
    def setUp(self):
        self.params = {}
        self.unknowns = {}
        self.resid = None

        self.params['z_full_in'] = np.linspace(0, 50.0, NPTS)
        self.params['z_param_in'] = np.array([0.0, 20.0, 50.0])
        self.params['section_height'] = np.array([20.0, 30.0])
        self.params['section_center_of_mass'],_ = nodal2sectional( self.params['z_full_in'] )
        self.params['freeboard'] = 15.0
        self.params['water_depth'] = 100.0
        self.params['stiffener_web_thickness'] = np.array([0.5, 0.5])
        self.params['stiffener_flange_thickness'] = np.array([0.3, 0.3])
        self.params['stiffener_web_height']  = np.array([1.0, 1.0])
        self.params['stiffener_flange_width'] = np.array([2.0, 2.0])
        self.params['stiffener_spacing'] = np.array([0.1, 0.1])
        self.params['Hs'] = 5.0
        self.params['max_draft'] = 70.0

        self.geom = column.ColumnGeometry(NSEC, NPTS)
Пример #13
0
    def setUp(self):
        self.params = {}
        self.unknowns = {}
        self.resid = None

        self.params['z_full_in'] = np.linspace(0, 50.0, NPTS)
        self.params['z_param_in'] = np.array([0.0, 20.0, 50.0])
        self.params['section_height'] = np.array([20.0, 30.0])
        self.params['section_center_of_mass'], _ = nodal2sectional(
            self.params['z_full_in'])
        self.params['freeboard'] = 15.0
        self.params['water_depth'] = 100.0
        self.params['stiffener_web_thickness'] = np.array([0.5, 0.5])
        self.params['stiffener_flange_thickness'] = np.array([0.3, 0.3])
        self.params['stiffener_web_height'] = np.array([1.0, 1.0])
        self.params['stiffener_flange_width'] = np.array([2.0, 2.0])
        self.params['stiffener_spacing'] = np.array([0.1, 0.1])
        self.params['Hs'] = 5.0
        self.params['max_draft'] = 70.0

        self.geom = column.ColumnGeometry(NSEC, NPTS)
Пример #14
0
    def setUp(self):
        self.params = {}
        self.unknowns = {}
        self.resid = None

        # Use the API 2U Appendix B as a big unit test!
        ksi_to_si = 6894757.29317831
        lbperft3_to_si = 16.0185
        ft_to_si = 0.3048
        in_to_si = ft_to_si / 12.0
        kip_to_si = 4.4482216 * 1e3

        onepts = np.ones((NPTS, ))
        onesec = np.ones((NPTS - 1, ))
        #onesec0 = np.ones((NSEC,))
        self.params['d_full'] = 600 * onepts * in_to_si
        self.params['t_full'] = 0.75 * onesec * in_to_si
        self.params['t_web'] = 5. / 8. * onesec * in_to_si
        self.params['h_web'] = 14.0 * onesec * in_to_si
        self.params['t_flange'] = 1.0 * onesec * in_to_si
        self.params['w_flange'] = 10.0 * onesec * in_to_si
        self.params['L_stiffener'] = 5.0 * onesec * ft_to_si
        #self.params['section_height'] = 50.0 * onesec0 * ft_to_si
        self.params['pressure'] = (64.0 * lbperft3_to_si) * g * (
            60 * ft_to_si) * onepts
        self.params['E'] = 29e3 * ksi_to_si
        self.params['nu'] = 0.3
        self.params['yield_stress'] = 50 * ksi_to_si
        self.params['wave_height'] = 0.0  # gives only static pressure
        self.params['stack_mass_in'] = 9000 * kip_to_si / g
        self.params['section_mass'] = 0.0 * np.ones((NPTS - 1, ))
        self.params['loading'] = 'radial'
        self.params['z_full'] = np.linspace(0, 1, NPTS)
        self.params['z_section'], _ = nodal2sectional(self.params['z_full'])
        self.params['z_param'] = np.linspace(0, 1, NSEC + 1)
        self.params['gamma_f'] = 1.0
        self.params['gamma_b'] = 1.0

        self.buckle = column.ColumnBuckling(NSEC, NPTS)
Пример #15
0
    def setUp(self):
        self.params = {}
        self.unknowns = {}
        self.resid = None

        # Use the API 2U Appendix B as a big unit test!
        ksi_to_si = 6894757.29317831
        lbperft3_to_si = 16.0185
        ft_to_si = 0.3048
        in_to_si = ft_to_si / 12.0
        kip_to_si = 4.4482216 * 1e3

        onepts  = np.ones((NPTS,))
        onesec  = np.ones((NPTS-1,))
        #onesec0 = np.ones((NSEC,))
        self.params['d_full'] = 600 * onepts * in_to_si
        self.params['t_full'] = 0.75 * onesec * in_to_si
        self.params['t_web'] = 5./8. * onesec * in_to_si
        self.params['h_web'] = 14.0 * onesec * in_to_si
        self.params['t_flange'] = 1.0 * onesec * in_to_si
        self.params['w_flange'] = 10.0 * onesec * in_to_si
        self.params['L_stiffener'] = 5.0 * onesec * ft_to_si
        #self.params['section_height'] = 50.0 * onesec0 * ft_to_si
        self.params['pressure'] = (64.0*lbperft3_to_si) * g * (60*ft_to_si) * onepts
        self.params['E'] = 29e3 * ksi_to_si
        self.params['nu'] = 0.3
        self.params['yield_stress'] = 50 * ksi_to_si
        self.params['wave_height'] = 0.0 # gives only static pressure
        self.params['stack_mass_in'] = 9000 * kip_to_si/g
        self.params['section_mass'] = 0.0 * np.ones((NPTS-1,))
        self.params['loading'] = 'radial'
        self.params['z_full'] = np.linspace(0, 1, NPTS)
        self.params['z_section'],_ = nodal2sectional( self.params['z_full'] )
        self.params['z_param'] = np.linspace(0, 1, NSEC+1)
        self.params['gamma_f'] = 1.0
        self.params['gamma_b'] = 1.0

        self.buckle = column.ColumnBuckling(NSEC, NPTS)
Пример #16
0
    def solve_nonlinear(self, params, unknowns, resids):
        # Unpack variables
        R_od, _ = nodal2sectional(params['d_full'])  # at section nodes
        R_od *= 0.5
        t_wall, _ = nodal2sectional(params['t_full'])  # at section nodes
        z_full = params['z_full']  # at section nodes
        z_param = params['z_param']
        z_section, _ = nodal2sectional(params['z_full'])
        h_section = np.diff(z_full)
        t_web = sectionalInterp(z_section, z_param,
                                params['stiffener_web_thickness'])
        t_flange = sectionalInterp(z_section, z_param,
                                   params['stiffener_flange_thickness'])
        h_web = sectionalInterp(z_section, z_param,
                                params['stiffener_web_height'])
        w_flange = sectionalInterp(z_section, z_param,
                                   params['stiffener_flange_width'])
        L_stiffener = sectionalInterp(z_section, z_param,
                                      params['stiffener_spacing'])
        rho = params['rho']

        # Outer and inner radius of web by section
        R_wo = R_od - t_wall
        R_wi = R_wo - h_web
        # Outer and inner radius of flange by section
        R_fo = R_wi
        R_fi = R_fo - t_flange

        # Material volumes by section
        V_web = np.pi * (R_wo**2 - R_wi**2) * t_web
        V_flange = np.pi * (R_fo**2 - R_fi**2) * w_flange

        # Ring mass by volume by section
        # Include fudge factor for design features not captured in this simple approach
        m_web = params['ring_mass_factor'] * rho * V_web
        m_flange = params['ring_mass_factor'] * rho * V_flange
        m_ring = m_web + m_flange
        n_stiff = np.zeros(z_section.shape, dtype=np.int_)

        # Compute moments of inertia for stiffeners (lumped by section for simplicity) at keel
        I_web = I_tube(R_wi, R_wo, t_web, m_web)
        I_flange = I_tube(R_fi, R_fo, w_flange, m_flange)
        I_ring = I_web + I_flange
        I_keel = np.zeros((3, 3))

        # Now march up the column, adding stiffeners at correct spacing until we are done
        z_stiff = []
        isection = 0
        epsilon = 1e-6
        while True:
            if len(z_stiff) == 0:
                z_march = np.minimum(z_full[isection + 1], z_full[0] +
                                     0.5 * L_stiffener[isection]) + epsilon
            else:
                z_march = np.minimum(z_full[isection + 1], z_stiff[-1] +
                                     L_stiffener[isection]) + epsilon
            if z_march >= z_full[-1]: break

            isection = np.searchsorted(z_full, z_march) - 1

            if len(z_stiff) == 0:
                add_stiff = (z_march -
                             z_full[0]) >= 0.5 * L_stiffener[isection]
            else:
                add_stiff = (z_march - z_stiff[-1]) >= L_stiffener[isection]

            if add_stiff:
                z_stiff.append(z_march)
                n_stiff[isection] += 1

                R = np.array([0.0, 0.0, (z_march - z_full[0])])
                Icg = assembleI(I_ring[isection, :])
                I_keel += Icg + m_ring[isection] * (np.dot(R, R) * np.eye(3) -
                                                    np.outer(R, R))

        # Number of stiffener rings per section (height of section divided by spacing)
        unknowns['stiffener_mass'] = n_stiff * m_ring

        # Find total number of stiffeners in each original section
        npts_per = z_section.size / (z_param.size - 1)
        n_stiff_sec = np.zeros(z_param.size - 1)
        for k in range(npts_per):
            n_stiff_sec += n_stiff[k::npts_per]
        unknowns['number_of_stiffeners'] = n_stiff_sec

        # Store results
        unknowns['stiffener_I_keel'] = unassembleI(I_keel)

        # Create some constraints for reasonable stiffener designs for an optimizer
        unknowns['flange_spacing_ratio'] = w_flange / (0.5 * L_stiffener)
        unknowns['stiffener_radius_ratio'] = (h_web + t_flange + t_wall) / R_od
Пример #17
0
    prob['pre1.rna_F'] = np.array([Fx1, Fy1, Fz1])
    prob['pre1.rna_M'] = np.array([Mxx1, Myy1, Mzz1])
    # # ---------------


    # # --- loading case 2: max Wind Speed ---
    prob['wind2.Uref'] = wind_Uref2

    prob['pre2.rna_F'] = np.array([Fx2, Fy2, Fz2])
    prob['pre2.rna_M' ] = np.array([Mxx2, Myy2, Mzz2])

    # # --- run ---
    prob.run()

    z,_ = nodal2sectional(prob['z_full'])

    print('zs=', z)
    print('ds=', prob['d_full'])
    print('ts=', prob['t_full'])
    print('mass (kg) =', prob['tower_mass'])
    print('cg (m) =', prob['tower_center_of_mass'])
    print('weldability =', prob['weldability'])
    print('manufacturability =', prob['manufacturability'])
    print('\nwind: ', prob['wind1.Uref'])
    print('f1 (Hz) =', prob['tower1.f1'])
    print('top_deflection1 (m) =', prob['post1.top_deflection'])
    print('stress1 =', prob['post1.stress'])
    print('GL buckling =', prob['post1.global_buckling'])
    print('Shell buckling =', prob['post1.shell_buckling'])
    print('damage =', prob['post1.damage'])
Пример #18
0
 def testNodal2Sectional(self):
     x,dx = util.nodal2sectional(np.array([8.0, 10.0, 12.0]))
     npt.assert_equal(x, np.array([9.0, 11.0]))
     npt.assert_equal(dx, np.array([[0.5, 0.5, 0.0],[0.0, 0.5, 0.5]]))
Пример #19
0
    def setUp(self):
        self.params = {}
        self.unknowns = {}
        self.resid = None

        # For Geometry call
        self.params['z_full_in'] = np.linspace(0, 50.0, NPTS)
        self.params['z_param_in'] = np.array([0.0, 20.0, 50.0])
        self.params['section_height'] = np.array([20.0, 30.0])
        self.params['section_center_of_mass'], _ = nodal2sectional(
            self.params['z_full_in'])
        self.params['freeboard'] = 15.0
        self.params['fairlead'] = 10.0
        self.params['water_depth'] = 100.0
        self.params['Hs'] = 5.0
        self.params['max_draft'] = 70.0

        self.params['t_full'] = 0.5 * secones
        self.params['d_full'] = 2 * 10.0 * myones

        self.params['stack_mass_in'] = 0.0

        self.params['shell_I_keel'] = 1e5 * np.array(
            [1.0, 1.0, 1.0, 0.0, 0.0, 0.0])
        self.params['stiffener_I_keel'] = 2e5 * np.array(
            [1.0, 1.0, 1.0, 0.0, 0.0, 0.0])
        self.params['bulkhead_I_keel'] = 3e5 * np.array(
            [1.0, 1.0, 1.0, 0.0, 0.0, 0.0])
        self.params['buoyancy_tank_I_keel'] = 5e6 * np.array(
            [1.0, 1.0, 1.0, 0.0, 0.0, 0.0])
        self.params['ballast_I_keel'] = 2e3 * np.array(
            [1.0, 1.0, 1.0, 0.0, 0.0, 0.0])

        self.params['buoyancy_tank_diameter'] = 15.0

        self.params['water_density'] = 1e3
        self.params['bulkhead_mass'] = 10.0 * myones
        self.params['shell_mass'] = 500.0 * np.ones(NPTS - 1)
        self.params['stiffener_mass'] = 100.0 * np.ones(NPTS - 1)
        self.params['ballast_mass'] = 20.0 * np.ones(NPTS - 1)
        self.params['ballast_z_cg'] = -35.0

        self.params['buoyancy_tank_mass'] = 20.0
        self.params['buoyancy_tank_cg'] = -15.0
        self.params['buoyancy_tank_location'] = 0.3
        self.params['buoyancy_tank_displacement'] = 300.0
        self.params['column_mass_factor'] = 1.1
        self.params['outfitting_mass_fraction'] = 0.05

        self.params['shell_cost'] = 1.0
        self.params['stiffener_cost'] = 2.0
        self.params['bulkhead_cost'] = 3.0
        self.params['buoyancy_tank_cost'] = 4.0
        self.params['ballast_cost'] = 5.0

        self.params['mooring_mass'] = 50.0
        self.params['mooring_vertical_load'] = 25.0
        self.params['mooring_restoring_force'] = 1e5
        self.params['mooring_cost'] = 1e4

        self.params['outfitting_cost_rate'] = 1.0

        self.params['stiffener_web_thickness'] = np.array([0.5, 0.5])
        self.params['stiffener_flange_thickness'] = np.array([0.3, 0.3])
        self.params['stiffener_web_height'] = np.array([1.0, 1.0])
        self.params['stiffener_flange_width'] = np.array([2.0, 2.0])
        self.params['stiffener_spacing'] = np.array([0.1, 0.1])

        self.geom = column.ColumnGeometry(NSEC, NPTS)
        self.set_geometry()

        self.mycolumn = column.ColumnProperties(NPTS)
Пример #20
0
    def setUp(self):
        self.params = {}
        self.unknowns = {}
        self.resid = None

        # For Geometry call
        self.params['z_full_in'] = np.linspace(0, 50.0, NPTS)
        self.params['z_param_in'] = np.array([0.0, 20.0, 50.0])
        self.params['section_height'] = np.array([20.0, 30.0])
        self.params['section_center_of_mass'],_ = nodal2sectional( self.params['z_full_in'] )
        self.params['freeboard'] = 15.0
        self.params['fairlead'] = 10.0
        self.params['water_depth'] = 100.0
        self.params['Hs'] = 5.0
        self.params['max_draft'] = 70.0
        
        self.params['t_full'] = 0.5*secones
        self.params['d_full'] = 2*10.0*myones

        self.params['stack_mass_in'] = 0.0

        self.params['shell_I_keel'] = 1e5 * np.array([1.0, 1.0, 1.0, 0.0, 0.0, 0.0])
        self.params['stiffener_I_keel'] = 2e5 * np.array([1.0, 1.0, 1.0, 0.0, 0.0, 0.0])
        self.params['bulkhead_I_keel'] = 3e5 * np.array([1.0, 1.0, 1.0, 0.0, 0.0, 0.0])
        self.params['buoyancy_tank_I_keel'] = 5e6 * np.array([1.0, 1.0, 1.0, 0.0, 0.0, 0.0])
        self.params['ballast_I_keel'] = 2e3 * np.array([1.0, 1.0, 1.0, 0.0, 0.0, 0.0])

        self.params['buoyancy_tank_diameter'] = 15.0
        
        self.params['water_density'] = 1e3
        self.params['bulkhead_mass'] = 10.0*myones
        self.params['shell_mass'] = 500.0*np.ones(NPTS-1)
        self.params['stiffener_mass'] = 100.0*np.ones(NPTS-1)
        self.params['ballast_mass'] = 20.0*np.ones(NPTS-1)
        self.params['ballast_z_cg'] = -35.0
        
        self.params['buoyancy_tank_mass'] = 20.0
        self.params['buoyancy_tank_cg'] = -15.0
        self.params['buoyancy_tank_location'] = 0.3
        self.params['buoyancy_tank_displacement'] = 300.0
        self.params['column_mass_factor'] = 1.1
        self.params['outfitting_mass_fraction'] = 0.05

        self.params['shell_cost'] = 1.0
        self.params['stiffener_cost'] = 2.0
        self.params['bulkhead_cost'] = 3.0
        self.params['buoyancy_tank_cost'] = 4.0
        self.params['ballast_cost'] = 5.0
        
        self.params['mooring_mass'] = 50.0
        self.params['mooring_vertical_load'] = 25.0
        self.params['mooring_restoring_force'] = 1e5
        self.params['mooring_cost'] = 1e4

        self.params['outfitting_cost_rate'] = 1.0

        self.params['stiffener_web_thickness'] = np.array([0.5, 0.5])
        self.params['stiffener_flange_thickness'] = np.array([0.3, 0.3])
        self.params['stiffener_web_height']  = np.array([1.0, 1.0])
        self.params['stiffener_flange_width'] = np.array([2.0, 2.0])
        self.params['stiffener_spacing'] = np.array([0.1, 0.1])
        
        self.geom = column.ColumnGeometry(NSEC, NPTS)
        self.set_geometry()

        self.mycolumn = column.ColumnProperties(NPTS)
Пример #21
0
    def solve_nonlinear(self, params, unknowns, resids):

        # ------- node data ----------------
        z = params['z']
        n = len(z)
        node = np.arange(1, n+1)
        x = np.zeros(n)
        y = np.zeros(n)
        r = np.zeros(n)

        nodes = frame3dd.NodeData(node, x, y, z, r)
        # -----------------------------------

        # ------ reaction data ------------

        # rigid base
        node = params['kidx'] + np.ones(len(params['kidx']), dtype=np.int_)  # add one because 0-based index but 1-based node numbering
        rigid = float('inf')

        reactions = frame3dd.ReactionData(node, params['kx'], params['ky'], params['kz'], params['ktx'], params['kty'], params['ktz'], rigid)
        # -----------------------------------

        # ------ frame element data ------------
        element = np.arange(1, n)
        N1 = np.arange(1, n)
        N2 = np.arange(2, n+1)

        roll = np.zeros(n-1)

        # average across element b.c. frame3dd uses constant section elements
        # TODO: Use nodal2sectional
        Az  = params['Az']
        Asx = params['Asx']
        Asy = params['Asy']
        Jz  = params['Jz']
        Ixx = params['Ixx']
        Iyy = params['Iyy']
        E   = params['E']*np.ones(Az.shape)
        G   = params['G']*np.ones(Az.shape)
        rho = params['rho']*np.ones(Az.shape)

        elements = frame3dd.ElementData(element, N1, N2, Az, Asx, Asy, Jz, Ixx, Iyy, E, G, roll, rho)
        # -----------------------------------


        # ------ options ------------
        options = frame3dd.Options(params['shear'], params['geom'], params['dx'])
        # -----------------------------------

        # initialize frame3dd object
        cylinder = frame3dd.Frame(nodes, reactions, elements, options)


        # ------ add extra mass ------------

        # extra node inertia data
        N = params['midx'] + np.ones(len(params['midx']), dtype=np.int_)

        cylinder.changeExtraNodeMass(N, params['m'], params['mIxx'], params['mIyy'], params['mIzz'], params['mIxy'], params['mIxz'], params['mIyz'],
            params['mrhox'], params['mrhoy'], params['mrhoz'], params['addGravityLoadForExtraMass'])

        # ------------------------------------

        # ------- enable dynamic analysis ----------
        cylinder.enableDynamics(params['nM'], params['Mmethod'], params['lump'], params['tol'], params['shift'])
        # ----------------------------

        # ------ static load case 1 ------------

        # gravity in the X, Y, Z, directions (global)
        gx = 0.0
        gy = 0.0
        gz = -gravity

        load = frame3dd.StaticLoadCase(gx, gy, gz)

        # point loads
        nF = params['plidx'] + np.ones(len(params['plidx']), dtype=int)
        load.changePointLoads(nF, params['Fx'], params['Fy'], params['Fz'], params['Mxx'], params['Myy'], params['Mzz'])

        # distributed loads
        Px, Py, Pz = params['Pz'], params['Py'], -params['Px']  # switch to local c.s.
        z = params['z']

        # trapezoidally distributed loads
        EL = np.arange(1, n)
        xx1 = xy1 = xz1 = np.zeros(n-1)
        xx2 = xy2 = xz2 = np.diff(z) - 1e-6  # subtract small number b.c. of precision
        wx1 = Px[:-1]
        wx2 = Px[1:]
        wy1 = Py[:-1]
        wy2 = Py[1:]
        wz1 = Pz[:-1]
        wz2 = Pz[1:]

        load.changeTrapezoidalLoads(EL, xx1, xx2, wx1, wx2, xy1, xy2, wy1, wy2, xz1, xz2, wz1, wz2)

        cylinder.addLoadCase(load)
        # Debugging
        #cylinder.write('temp.3dd')
        # -----------------------------------
        # run the analysis
        displacements, forces, reactions, internalForces, mass, modal = cylinder.run()
        iCase = 0

        # mass
        unknowns['mass'] = mass.struct_mass

        # natural frequncies
        unknowns['f1'] = modal.freq[0]
        unknowns['f2'] = modal.freq[1]

        # deflections due to loading (from cylinder top and wind/wave loads)
        unknowns['top_deflection'] = displacements.dx[iCase, n-1]  # in yaw-aligned direction

        # shear and bending, one per element (convert from local to global c.s.)
        Fz = forces.Nx[iCase, 1::2]
        Vy = forces.Vy[iCase, 1::2]
        Vx = -forces.Vz[iCase, 1::2]

        Mzz = forces.Txx[iCase, 1::2]
        Myy = forces.Myy[iCase, 1::2]
        Mxx = -forces.Mzz[iCase, 1::2]

        # Record total forces and moments
        unknowns['base_F'] = -1.0 * np.array([reactions.Fx.sum(), reactions.Fy.sum(), reactions.Fz.sum()])
        unknowns['base_M'] = -1.0 * np.array([reactions.Mxx.sum(), reactions.Myy.sum(), reactions.Mzz.sum()])

        unknowns['Fz_out']  = Fz
        unknowns['Vx_out']  = Vx
        unknowns['Vy_out']  = Vy
        unknowns['Mxx_out'] = Mxx
        unknowns['Myy_out'] = Myy
        unknowns['Mzz_out'] = Mzz

        # axial and shear stress
        d,_    = nodal2sectional(params['d'])
        qdyn,_ = nodal2sectional(params['qdyn'])
        
        ##R = self.d/2.0
        ##x_stress = R*np.cos(self.theta_stress)
        ##y_stress = R*np.sin(self.theta_stress)
        ##axial_stress = Fz/self.Az + Mxx/self.Ixx*y_stress - Myy/self.Iyy*x_stress
#        V = Vy*x_stress/R - Vx*y_stress/R  # shear stress orthogonal to direction x,y
#        shear_stress = 2. * V / self.Az  # coefficient of 2 for a hollow circular section, but should be conservative for other shapes
        unknowns['axial_stress'] = Fz/params['Az'] - np.sqrt(Mxx**2+Myy**2)/params['Iyy']*d/2.0  #More conservative, just use the tilted bending and add total max shear as well at the same point, if you do not like it go back to the previous lines

        unknowns['shear_stress'] = 2. * np.sqrt(Vx**2+Vy**2) / params['Az'] # coefficient of 2 for a hollow circular section, but should be conservative for other shapes

        # hoop_stress (Eurocode method)
        L_reinforced = params['L_reinforced'] * np.ones(Fz.shape)
        unknowns['hoop_stress_euro'] = hoopStressEurocode(params['z'], d, params['t'], L_reinforced, qdyn)

        # Simpler hoop stress used in API calculations
        unknowns['hoop_stress'] = hoopStress(d, params['t'], qdyn)
Пример #22
0
 def testNodal2Sectional(self):
     x, dx = util.nodal2sectional(np.array([8.0, 10.0, 12.0]))
     npt.assert_equal(x, np.array([9.0, 11.0]))
     npt.assert_equal(dx, np.array([[0.5, 0.5, 0.0], [0.0, 0.5, 0.5]]))
Пример #23
0
    def solve_nonlinear(self, params, unknowns, resids):

        # ------- node data ----------------
        z = params['z']
        n = len(z)
        node = np.arange(1, n + 1)
        x = np.zeros(n)
        y = np.zeros(n)
        r = np.zeros(n)

        nodes = frame3dd.NodeData(node, x, y, z, r)
        # -----------------------------------

        # ------ reaction data ------------

        # rigid base
        node = params['kidx'] + np.ones(
            len(params['kidx']), dtype=np.int_
        )  # add one because 0-based index but 1-based node numbering
        rigid = float('inf')

        reactions = frame3dd.ReactionData(node, params['kx'], params['ky'],
                                          params['kz'], params['ktx'],
                                          params['kty'], params['ktz'], rigid)
        # -----------------------------------

        # ------ frame element data ------------
        element = np.arange(1, n)
        N1 = np.arange(1, n)
        N2 = np.arange(2, n + 1)

        roll = np.zeros(n - 1)

        # average across element b.c. frame3dd uses constant section elements
        # TODO: Use nodal2sectional
        Az = params['Az']
        Asx = params['Asx']
        Asy = params['Asy']
        Jz = params['Jz']
        Ixx = params['Ixx']
        Iyy = params['Iyy']
        E = params['E'] * np.ones(Az.shape)
        G = params['G'] * np.ones(Az.shape)
        rho = params['rho'] * np.ones(Az.shape)

        elements = frame3dd.ElementData(element, N1, N2, Az, Asx, Asy, Jz, Ixx,
                                        Iyy, E, G, roll, rho)
        # -----------------------------------

        # ------ options ------------
        options = frame3dd.Options(params['shear'], params['geom'],
                                   params['dx'])
        # -----------------------------------

        # initialize frame3dd object
        cylinder = frame3dd.Frame(nodes, reactions, elements, options)

        # ------ add extra mass ------------

        # extra node inertia data
        N = params['midx'] + np.ones(len(params['midx']), dtype=np.int_)

        cylinder.changeExtraNodeMass(N, params['m'], params['mIxx'],
                                     params['mIyy'], params['mIzz'],
                                     params['mIxy'], params['mIxz'],
                                     params['mIyz'], params['mrhox'],
                                     params['mrhoy'], params['mrhoz'],
                                     params['addGravityLoadForExtraMass'])

        # ------------------------------------

        # ------- enable dynamic analysis ----------
        cylinder.enableDynamics(params['nM'], params['Mmethod'],
                                params['lump'], params['tol'], params['shift'])
        # ----------------------------

        # ------ static load case 1 ------------

        # gravity in the X, Y, Z, directions (global)
        gx = 0.0
        gy = 0.0
        gz = -gravity

        load = frame3dd.StaticLoadCase(gx, gy, gz)

        # point loads
        nF = params['plidx'] + np.ones(len(params['plidx']), dtype=int)
        load.changePointLoads(nF, params['Fx'], params['Fy'], params['Fz'],
                              params['Mxx'], params['Myy'], params['Mzz'])

        # distributed loads
        Px, Py, Pz = params['Pz'], params['Py'], -params[
            'Px']  # switch to local c.s.
        z = params['z']

        # trapezoidally distributed loads
        EL = np.arange(1, n)
        xx1 = xy1 = xz1 = np.zeros(n - 1)
        xx2 = xy2 = xz2 = np.diff(
            z) - 1e-6  # subtract small number b.c. of precision
        wx1 = Px[:-1]
        wx2 = Px[1:]
        wy1 = Py[:-1]
        wy2 = Py[1:]
        wz1 = Pz[:-1]
        wz2 = Pz[1:]

        load.changeTrapezoidalLoads(EL, xx1, xx2, wx1, wx2, xy1, xy2, wy1, wy2,
                                    xz1, xz2, wz1, wz2)

        cylinder.addLoadCase(load)
        # Debugging
        #cylinder.write('temp.3dd')
        # -----------------------------------
        # run the analysis
        displacements, forces, reactions, internalForces, mass, modal = cylinder.run(
        )
        iCase = 0

        # mass
        unknowns['mass'] = mass.struct_mass

        # natural frequncies
        unknowns['f1'] = modal.freq[0]
        unknowns['f2'] = modal.freq[1]

        # deflections due to loading (from cylinder top and wind/wave loads)
        unknowns['top_deflection'] = displacements.dx[
            iCase, n - 1]  # in yaw-aligned direction

        # shear and bending, one per element (convert from local to global c.s.)
        Fz = forces.Nx[iCase, 1::2]
        Vy = forces.Vy[iCase, 1::2]
        Vx = -forces.Vz[iCase, 1::2]

        Mzz = forces.Txx[iCase, 1::2]
        Myy = forces.Myy[iCase, 1::2]
        Mxx = -forces.Mzz[iCase, 1::2]

        # Record total forces and moments
        unknowns['base_F'] = -1.0 * np.array(
            [reactions.Fx.sum(),
             reactions.Fy.sum(),
             reactions.Fz.sum()])
        unknowns['base_M'] = -1.0 * np.array(
            [reactions.Mxx.sum(),
             reactions.Myy.sum(),
             reactions.Mzz.sum()])

        unknowns['Fz_out'] = Fz
        unknowns['Vx_out'] = Vx
        unknowns['Vy_out'] = Vy
        unknowns['Mxx_out'] = Mxx
        unknowns['Myy_out'] = Myy
        unknowns['Mzz_out'] = Mzz

        # axial and shear stress
        d, _ = nodal2sectional(params['d'])
        qdyn, _ = nodal2sectional(params['qdyn'])

        ##R = self.d/2.0
        ##x_stress = R*np.cos(self.theta_stress)
        ##y_stress = R*np.sin(self.theta_stress)
        ##axial_stress = Fz/self.Az + Mxx/self.Ixx*y_stress - Myy/self.Iyy*x_stress
        #        V = Vy*x_stress/R - Vx*y_stress/R  # shear stress orthogonal to direction x,y
        #        shear_stress = 2. * V / self.Az  # coefficient of 2 for a hollow circular section, but should be conservative for other shapes
        unknowns['axial_stress'] = Fz / params['Az'] - np.sqrt(
            Mxx**2 + Myy**2
        ) / params[
            'Iyy'] * d / 2.0  #More conservative, just use the tilted bending and add total max shear as well at the same point, if you do not like it go back to the previous lines

        unknowns['shear_stress'] = 2. * np.sqrt(Vx**2 + Vy**2) / params[
            'Az']  # coefficient of 2 for a hollow circular section, but should be conservative for other shapes

        # hoop_stress (Eurocode method)
        L_reinforced = params['L_reinforced'] * np.ones(Fz.shape)
        unknowns['hoop_stress_euro'] = hoopStressEurocode(
            params['z'], d, params['t'], L_reinforced, qdyn)

        # Simpler hoop stress used in API calculations
        unknowns['hoop_stress'] = hoopStress(d, params['t'], qdyn)