Exemple #1
0
    def create(self):
        """Actually create the imperfection

        This modifies all composite layups to replace their existing (constant)
        ply orientations with values that are defined by a discrete field.

        .. note:: Must be called from Abaqus.

        """
        from abaqus import mdb
        from abaqusConstants import ANGLE_0, ROTATION_FIELD
        from desicos.abaqus.abaqus_functions import modify_composite_layup

        cc = self.impconf.conecyl
        mod = mdb.models[cc.model_name]
        part = mod.parts[cc.part_name_shell]
        fields = self._create_orientation_fields(mod, part.elements)

        def modify_orientation(index, kwargs):
            kwargs['orientationType'] = ANGLE_0
            kwargs['additionalRotationType'] = ROTATION_FIELD
            kwargs['additionalRotationField'] = fields[index].name
            kwargs.pop('orientation', None)
            kwargs.pop('orientationValue', None)
            kwargs.pop('angle', None)
            return kwargs

        for layup_name, layup in part.compositeLayups.items():
            if not layup.suppressed:
                modify_composite_layup(part, layup_name, modify_orientation)
Exemple #2
0
    def update_after_tis(self):
        """Call this function after the thickness imperfection(s) are applied,
        to modify the material properties as well, if needed.

        """
        if not self.use_ti:
            return

        from abaqus import mdb
        from desicos.abaqus.abaqus_functions import modify_composite_layup

        cc = self.impconf.conecyl
        part = mdb.models[cc.model_name].parts[cc.part_name_shell]

        for layup_name in part.compositeLayups.keys():
            if layup_name.startswith('CLayup_'):
                layup = part.compositeLayups[layup_name]
                thickness = sum(p.thickness for p in layup.plies.values())
                scaling_factor = thickness / sum(cc.plyts)
                suffix = layup_name[-6:]
                self._update_material(suffix, scaling_factor)
                def modify_material(index, kwargs):
                    kwargs['material'] = cc.laminapropKeys[index] + suffix
                    return kwargs
                modify_composite_layup(part, layup_name, modify_material)
Exemple #3
0
    def create(self):
        """Actually create the imperfection

        This modifies all composite layups to replace their existing (constant)
        ply orientations with values that are defined by a discrete field.

        .. note:: Must be called from Abaqus.

        """
        from abaqus import mdb
        from abaqusConstants import ANGLE_0, ROTATION_FIELD
        from desicos.abaqus.abaqus_functions import modify_composite_layup

        cc = self.impconf.conecyl
        mod = mdb.models[cc.model_name]
        part = mod.parts[cc.part_name_shell]
        fields = self._create_orientation_fields(mod, part.elements)

        def modify_orientation(index, kwargs):
            kwargs['orientationType'] = ANGLE_0
            kwargs['additionalRotationType'] = ROTATION_FIELD
            kwargs['additionalRotationField'] = fields[index].name
            kwargs.pop('orientation', None)
            kwargs.pop('orientationValue', None)
            kwargs.pop('angle', None)
            return kwargs

        for layup_name, layup in part.compositeLayups.items():
            if not layup.suppressed:
                modify_composite_layup(part, layup_name, modify_orientation)
Exemple #4
0
    def update_after_tis(self):
        """Call this function after the thickness imperfection(s) are applied,
        to modify the material properties as well, if needed.

        """
        if not self.use_ti:
            return

        from abaqus import mdb
        from desicos.abaqus.abaqus_functions import modify_composite_layup

        cc = self.impconf.conecyl
        part = mdb.models[cc.model_name].parts[cc.part_name_shell]

        for layup_name in part.compositeLayups.keys():
            if layup_name.startswith('CLayup_'):
                layup = part.compositeLayups[layup_name]
                thickness = sum(p.thickness for p in layup.plies.values())
                scaling_factor = thickness / sum(cc.plyts)
                suffix = layup_name[-6:]
                self._update_material(suffix, scaling_factor)

                def modify_material(index, kwargs):
                    kwargs['material'] = cc.laminapropKeys[index] + suffix
                    return kwargs

                modify_composite_layup(part, layup_name, modify_material)
Exemple #5
0
    def create(self):
        """Actually create the imperfection

        .. note:: Must be called from Abaqus.

        """
        from abaqus import mdb
        from desicos.abaqus.abaqus_functions import modify_composite_layup

        cc = self.impconf.conecyl
        part = mdb.models[cc.model_name].parts[cc.part_name_shell]

        if self.global_sf is not None:
            MAT_SUFFIX = '_scaled'
            self._update_material(MAT_SUFFIX, self.global_sf)

            def modify_mat_thick(index, kwargs):
                kwargs['thickness'] = cc.plyts[index] * self.global_sf
                kwargs['material'] = cc.laminapropKeys[index] + MAT_SUFFIX
                return kwargs

            modify_composite_layup(part, 'CompositePlate', modify_mat_thick)

        self.update_after_tis()
        self.created = True
Exemple #6
0
    def create(self):
        """Actually create the imperfection

        .. note:: Must be called from Abaqus.

        """
        from abaqus import mdb
        from desicos.abaqus.abaqus_functions import modify_composite_layup

        cc = self.impconf.conecyl
        part = mdb.models[cc.model_name].parts[cc.part_name_shell]

        if self.global_sf is not None:
            MAT_SUFFIX = '_scaled'
            self._update_material(MAT_SUFFIX, self.global_sf)
            def modify_mat_thick(index, kwargs):
                kwargs['thickness'] = cc.plyts[index] * self.global_sf
                kwargs['material'] = cc.laminapropKeys[index] + MAT_SUFFIX
                return kwargs
            modify_composite_layup(part, 'CompositePlate', modify_mat_thick)

        self.update_after_tis()
        self.created = True
def change_thickness_ABAQUS(imperfection_file_name,
                            model_name,
                            part_name,
                            stack,
                            t_model,
                            t_measured,
                            H_model,
                            H_measured,
                            R_model,
                            R_best_fit=None,
                            number_of_sets=None,
                            semi_angle=0.,
                            stretch_H=False,
                            z_offset_bot=None,
                            scaling_factor=1.,
                            num_closest_points=5,
                            power_parameter=2,
                            elems_t=None,
                            t_set=None,
                            use_theta_z_format=False):
    r"""Applies a given thickness imperfection to the finite element model

    Assumes that a percentage variation of the laminate thickness can be
    represented by the same percentage veriation of each ply, i.e., each
    ply thickness is varied in order to reflect a given measured thickness
    imperfection field.

    Parameters
    ----------

    imperfection_file_name : str
        Full path to the imperfection file.
    model_name : str
        Model name.
    part_name : str
        Part name.
    stack : list
        The stacking sequence of the current model with each angle given in
        degrees.
    t_model : float
        The nominal shell thickness of the current model.
    t_measured : float
        The nominal thickness of the measured specimen.
    H_model : float
        Total height of the model where the imperfections will be applied to,
        considering also eventual resin rings.
    H_measured : float
        The total height of the measured test specimen, including eventual
        resin rings at the edges.
    R_model : float
        Radius **at the bottom edge** of the model where the imperfections
        will be applied to.
    R_best_fit : float, optional
        Best fit radius obtained with functions :func:`.best_fit_cylinder`
        or :func:`.best_fit_cone`.
    number_of_sets : int, optional
        Defines in how many levels the thicknesses should be divided. If
        ``None`` it will be based on the input file, and if the threshold
        of ``100`` is exceeded, ``10`` sections are used.
    semi_angle : float, optional
        Cone semi-vertex angle in degrees, when applicable.
    stretch_H : bool, optional
        If the measured imperfection data should be stretched to the current
        model (which may happen when ``H_model!=H_measured``.
    z_offset_bot : float, optional
        It is common to have the measured data not covering the whole test
        specimen, and therefore it will be centralized, if a non-centralized
        position is desired this parameter can be used for the adjustment.
    scaling_factor : float, optional
        A scaling factor that can be used to study the imperfection
        sensitivity.
    num_closest_points : int, optional
        See :func:`the inverse-weighted interpolation algorithm
        <.inv_weighted>`.
    power_parameter : float, optional
        See :func:`the inverse-weighted interpolation algorithm
        <.inv_weighted>`.
    elems_t : np.ndarray, optional
        Interpolated thickness for each element. Can be used to avoid the same
        interpolation to be performed twice.
    t_set : set, optional
        A ``set`` object containing the unique thicknesses that will be used
        to create the new properties.
    use_theta_z_format : bool, optional
        If the new format `\theta, Z, imp` should be used instead of the old
        `X, Y, Z`.

    """
    from abaqus import mdb

    import desicos.abaqus.abaqus_functions as abaqus_functions

    mod = mdb.models[model_name]
    part = mod.parts[part_name]
    part_cyl_csys = part.features['part_cyl_csys']
    part_cyl_csys = part.datums[part_cyl_csys.id]

    if use_theta_z_format:
        if elems_t is None or t_set is None:
            log('Reading coordinates for elements...')
            elements = vec_calc_elem_cg(part.elements)

            log('Coordinates for elements read!')
            d, d, data = read_theta_z_imp(path=imperfection_file_name,
                                          H_measured=H_measured,
                                          stretch_H=stretch_H,
                                          z_offset_bot=z_offset_bot)

            data3D = np.zeros((data.shape[0], 4), dtype=FLOAT)
            z = data[:, 1]
            z *= H_model

            alpharad = deg2rad(semi_angle)
            tana = tan(alpharad)

            def r_local(z):
                return R_model - z * tana

            data3D[:, 0] = r_local(z) * cos(data[:, 0])
            data3D[:, 1] = r_local(z) * sin(data[:, 0])
            data3D[:, 2] = z
            data3D[:, 3] = data[:, 2]

            dist, ans = inv_weighted(data3D,
                                     elements[:, :3],
                                     ncp=num_closest_points,
                                     power_parameter=power_parameter)

            t_set = set(ans)
            t_set.discard(0.)  #TODO why inv_weighted returns an array with 0.
            elems_t = np.zeros((elements.shape[0], 2), dtype=FLOAT)
            elems_t[:, 0] = elements[:, 3]
            elems_t[:, 1] = ans

        else:
            log('Thickness differences already calculated!')

    else:
        if elems_t is None or t_set is None:
            # reading elements data
            log('Reading coordinates for elements...')
            elements = vec_calc_elem_cg(part.elements)
            log('Coordinates for elements read!')
            # calling translate_nodes function
            elems_t, t_set = calc_elems_t(
                imperfection_file_name,
                nodes=elements,
                t_model=t_model,
                t_measured=t_measured,
                H_model=H_model,
                H_measured=H_measured,
                R_model=R_model,
                R_best_fit=R_best_fit,
                semi_angle=semi_angle,
                stretch_H=stretch_H,
                z_offset_bot=z_offset_bot,
                num_closest_points=num_closest_points,
                power_parameter=power_parameter)
        else:
            log('Thickness differences already calculated!')
    # creating sets
    t_list = []
    max_len_t_set = 100
    if len(t_set) >= max_len_t_set and number_of_sets in (None, 0):
        number_of_sets = 10
        log('More than {0:d} different thicknesses measured!'.format(
            max_len_t_set))
        log('Forcing a number_of_sets = {0:d}'.format(number_of_sets))
    if number_of_sets is None or number_of_sets == 0:
        number_of_sets = len(t_set)
        t_list = list(t_set)
        t_list.sort()
    else:
        t_min = min(t_set)
        t_max = max(t_set)
        t_list = list(np.linspace(t_min, t_max, number_of_sets + 1))

    # grouping elements
    sets_ids = [[] for i in range(len(t_list))]
    for entry in elems_t:
        elem_id, t = entry
        index = index_within_linspace(t_list, t)
        sets_ids[index].append(int(elem_id))
    # putting elements in sets
    original_layup = part.compositeLayups['CompositePlate']
    for i, set_ids in enumerate(sets_ids):
        if len(set_ids) == 0:
            # since t_set_norm * t_model <> t_set originally measured
            # there may be empty set_ids at the end
            continue
        elements = part.elements.sequenceFromLabels(labels=set_ids)
        suffix = 'measured_imp_t_{0:03d}'.format(i)
        set_name = 'Set_' + suffix
        log('Creating set ({0: 7d} elements): {1}'.format(
            len(set_ids), set_name))
        part.Set(name=set_name, elements=elements)
        region = part.sets[set_name]
        layup_name = 'CLayup_' + suffix
        t_diff = (float(t_list[i]) - t_model) * scaling_factor
        t_scaling_factor = (t_model + t_diff) / t_model

        def modify_ply(index, kwargs):
            kwargs['thickness'] *= t_scaling_factor
            kwargs['region'] = region
            return kwargs

        layup = part.CompositeLayup(name=layup_name,
                                    objectToCopy=original_layup)
        layup.resume()
        abaqus_functions.modify_composite_layup(part=part,
                                                layup_name=layup_name,
                                                modify_func=modify_ply)
    # suppress needed to put the new properties to the input file
    original_layup.suppress()

    return elems_t, t_set
def change_thickness_ABAQUS(imperfection_file_name,
                            model_name,
                            part_name,
                            stack,
                            t_model,
                            t_measured,
                            H_model,
                            H_measured,
                            R_model,
                            R_best_fit = None,
                            number_of_sets = None,
                            semi_angle = 0.,
                            stretch_H = False,
                            z_offset_bot = None,
                            scaling_factor = 1.,
                            num_closest_points = 5,
                            power_parameter = 2,
                            num_sec_z = 100,
                            elems_t = None,
                            t_set = None,
                            use_theta_z_format = False):
    r"""Applies a given thickness imperfection to the finite element model

    Assumes that a percentage variation of the laminate thickness can be
    represented by the same percentage veriation of each ply, i.e., each
    ply thickness is varied in order to reflect a given measured thickness
    imperfection field.

    Parameters
    ----------

    imperfection_file_name : str
        Full path to the imperfection file.
    model_name : str
        Model name.
    part_name : str
        Part name.
    stack : list
        The stacking sequence of the current model with each angle given in
        degrees.
    t_model : float
        The nominal shell thickness of the current model.
    t_measured : float
        The nominal thickness of the measured specimen.
    H_model : float
        Total height of the model where the imperfections will be applied to,
        considering also eventual resin rings.
    H_measured : float
        The total height of the measured test specimen, including eventual
        resin rings at the edges.
    R_model : float
        Radius **at the bottom edge** of the model where the imperfections
        will be applied to.
    R_best_fit : float, optional
        Best fit radius obtained with functions :func:`.best_fit_cylinder`
        or :func:`.best_fit_cone`.
    number_of_sets : int, optional
        Defines in how many levels the thicknesses should be divided. If
        ``None`` it will be based on the input file, and if the threshold
        of ``100`` is exceeded, ``10`` sections are used.
    semi_angle : float, optional
        Cone semi-vertex angle in degrees, when applicable.
    stretch_H : bool, optional
        If the measured imperfection data should be stretched to the current
        model (which may happen when ``H_model!=H_measured``.
    z_offset_bot : float, optional
        It is common to have the measured data not covering the whole test
        specimen, and therefore it will be centralized, if a non-centralized
        position is desired this parameter can be used for the adjustment.
    scaling_factor : float, optional
        A scaling factor that can be used to study the imperfection
        sensitivity.
    num_closest_points : int, optional
        See :func:`the inverse-weighted interpolation algorithm
        <.inv_weighted>`.
    power_parameter : float, optional
        See :func:`the inverse-weighted interpolation algorithm
        <.inv_weighted>`.
    num_sec_z : int, optional
        Number of spatial sections used to classify the measured data in order
        to accelerate the searching algorithms
    elems_t : np.ndarray, optional
        Interpolated thickness for each element. Can be used to avoid the same
        interpolation to be performed twice.
    t_set : set, optional
        A ``set`` object containing the unique thicknesses that will be used
        to create the new properties.
    use_theta_z_format : bool, optional
        If the new format `\theta, Z, imp` should be used instead of the old
        `X, Y, Z`.

    """
    from abaqus import mdb

    import desicos.abaqus.abaqus_functions as abaqus_functions

    mod = mdb.models[model_name]
    part = mod.parts[part_name]
    part_cyl_csys = part.features['part_cyl_csys']
    part_cyl_csys = part.datums[part_cyl_csys.id]

    if use_theta_z_format:
        if elems_t is None or t_set is None:
            log('Reading coordinates for elements...')
            elements = vec_calc_elem_cg(part.elements)

            log('Coordinates for elements read!')
            d, d, data = read_theta_z_imp(path = imperfection_file_name,
                                          H_measured = H_measured,
                                          stretch_H = stretch_H,
                                          z_offset_bot = z_offset_bot)

            data3D = np.zeros((data.shape[0], 4), dtype=FLOAT)
            z = data[:, 1]
            z *= H_model

            alpharad = deg2rad(semi_angle)
            tana = tan(alpharad)
            def r_local(z):
                return R_model - z*tana
            data3D[:, 0] = r_local(z)*cos(data[:, 0])
            data3D[:, 1] = r_local(z)*sin(data[:, 0])
            data3D[:, 2] = z
            data3D[:, 3] = data[:, 2]

            ans = inv_weighted(data3D, elements[:, :3],
                               num_sub = num_sec_z,
                               col = 2,
                               ncp = num_closest_points,
                               power_parameter = power_parameter)

            t_set = set(ans)
            t_set.discard(0.) #TODO why inv_weighted returns an array with 0.
            elems_t = np.zeros((elements.shape[0], 2), dtype=FLOAT)
            elems_t[:, 0] = elements[:, 3]
            elems_t[:, 1] = ans

        else:
            log('Thickness differences already calculated!')

    else:
        if elems_t is None or t_set is None:
            # reading elements data
            log('Reading coordinates for elements...')
            elements = vec_calc_elem_cg(part.elements)
            log('Coordinates for elements read!')
            # calling translate_nodes function
            elems_t, t_set = calc_elems_t(
                                imperfection_file_name,
                                nodes = elements,
                                t_model = t_model,
                                t_measured = t_measured,
                                H_model = H_model,
                                H_measured = H_measured,
                                R_model = R_model,
                                R_best_fit = R_best_fit,
                                semi_angle = semi_angle,
                                stretch_H = stretch_H,
                                z_offset_bot = z_offset_bot,
                                num_closest_points = num_closest_points,
                                power_parameter = power_parameter,
                                num_sec_z = num_sec_z)
        else:
            log('Thickness differences already calculated!')
    # creating sets
    t_list = []
    max_len_t_set = 100
    if len(t_set) >= max_len_t_set and number_of_sets in (None, 0):
        number_of_sets = 10
        log('More than {0:d} different thicknesses measured!'.format(
            max_len_t_set))
        log('Forcing a number_of_sets = {0:d}'.format(number_of_sets))
    if number_of_sets is None or number_of_sets == 0:
        number_of_sets = len(t_set)
        t_list = list(t_set)
        t_list.sort()
    else:
        t_min = min(t_set)
        t_max = max(t_set)
        t_list = list(np.linspace(t_min, t_max, number_of_sets+1))

    # grouping elements
    sets_ids = [[] for i in range(len(t_list))]
    for entry in elems_t:
        elem_id, t = entry
        index = index_within_linspace(t_list, t)
        sets_ids[index].append(int(elem_id))
    # putting elements in sets
    original_layup = part.compositeLayups['CompositePlate']
    for i, set_ids in enumerate(sets_ids):
        if len(set_ids) == 0:
            # since t_set_norm * t_model <> t_set originally measured
            # there may be empty set_ids at the end
            continue
        elements = part.elements.sequenceFromLabels(labels=set_ids)
        suffix = 'measured_imp_t_{0:03d}'.format(i)
        set_name = 'Set_' + suffix
        log('Creating set ({0: 7d} elements): {1}'.format(
            len(set_ids), set_name))
        part.Set(name = set_name, elements = elements)
        region = part.sets[set_name]
        layup_name = 'CLayup_' + suffix
        t_diff = (float(t_list[i]) - t_model) * scaling_factor
        t_scaling_factor = (t_model + t_diff)/t_model

        def modify_ply(index, kwargs):
            kwargs['thickness'] *= t_scaling_factor
            kwargs['region'] = region
            return kwargs

        layup = part.CompositeLayup(name=layup_name,
                                    objectToCopy=original_layup)
        layup.resume()
        abaqus_functions.modify_composite_layup(part=part,
            layup_name=layup_name, modify_func=modify_ply)
    # suppress needed to put the new properties to the input file
    original_layup.suppress()

    return elems_t, t_set