示例#1
0
    def add_ffi(self, nominal_vf, E_matrix, nu_matrix, use_ti, global_sf=None):
        """Adds Fiber Fraction Imperfection (FFI)

        There can be only one of these, so calling this function overrides the
        previous imperfection, if any.

        Parameters
        ----------
        nominal_vf : float
            Nominal fiber volume fraction of the material
        E_matrix : float
            Young's modulus of the matrix material
        nu_matrix : float
            Poisson's ratio of the matrix material
        use_ti : bool
            If ``True``, create varying material properties according to the
            thickness imperfection data (if present).
        global_sf : float or ``None``
            Global scaling factor to apply to the material thickness.
            Set to ``None`` to disable. The global scaling may be overridden
            by a thickness imperfection, if ``use_ti`` (see above) is ``True``.

        Returns
        -------
        ffi : :class:`.FFI` object.

        """
        if self.ffi is not None:
            warn('FFI object already set, overriding...')
        self.ffi = FFI(nominal_vf, E_matrix, nu_matrix, use_ti, global_sf)
        self.ffi.impconf = self
        return self.ffi
示例#2
0
def calc_msi_amplitude(cc, force=False):
    """Calculates the mid-surface imperfection of a ConeCyl model

    .. note:: Must be called from Abaqus.

    Parameters
    ----------
    cc : ConeCyl object
        The :class:`.ConeCyl` object already
    force : bool, optional
        Does not the check if the finite element model is already created.


    Returns
    -------
    max_amp : float
        The maximum absolute amplitude.

    """
    if not force and not cc.created_model:
        warn('The finite element for the input ConeCyl object is not created')
        return

    from abaqus import mdb

    part = mdb.models[cc.model_name].parts[cc.part_name_shell]
    coords = np.array([n.coordinates for n in part.nodes])
    xs, ys, zs = coords.T
    node_rs = (xs**2 + ys**2)**0.5
    pts = zs/cc.H
    rs, zs = cc.r_z_from_pt(pts)
    amps = (node_rs - rs)/np.cos(cc.alpharad)
    max_amp = max(np.absolute(amps))

    return max_amp
示例#3
0
    def add_ppi(self, info, extra_height):
        """Adds Ply Piece Imperfection (PPI)

        There can be only one of these, so calling this function overrides the
        previous imperfection, if any.
        Note: Applicable for cones only!

        Parameters
        ----------
        info : list
            List of dictionaries with info about the layup of this cone.
            See :class:`.PPI` for more details
        extra_height : float
            Extra height above and below the cone height (`cc.H`) to consider
            in the ply placement model.

        Returns
        -------
        ppi : :class:`.PPI` object.

        """
        if self.ppi is not None:
            warn('PPI object already set, overriding...')
        self.ppi = PPI(info, extra_height)
        self.ppi.impconf = self
        return self.ppi
示例#4
0
def calc_msi_amplitude(cc, force=False):
    """Calculates the mid-surface imperfection of a ConeCyl model

    .. note:: Must be called from Abaqus.

    Parameters
    ----------
    cc : ConeCyl object
        The :class:`.ConeCyl` object already
    force : bool, optional
        Does not the check if the finite element model is already created.


    Returns
    -------
    max_amp : float
        The maximum absolute amplitude.

    """
    if not force and not cc.created_model:
        warn('The finite element for the input ConeCyl object is not created')
        return

    from abaqus import mdb

    part = mdb.models[cc.model_name].parts[cc.part_name_shell]
    coords = np.array([n.coordinates for n in part.nodes])
    xs, ys, zs = coords.T
    node_rs = (xs**2 + ys**2)**0.5
    pts = zs/cc.H
    rs, zs = cc.r_z_from_pt(pts)
    amps = (node_rs - rs) * np.cos(cc.alpharad)
    max_amp = max(np.absolute(amps))

    return max_amp
示例#5
0
文件: pload.py 项目: yuscale/desicos
    def calc_amplitude(self):
        """Calculate the imperfection amplitude.

        The odb must be available and it will be used to extract the last
        frame of the first analysis step, corresponding to the constant loads.

        """
        from abaqus import mdb

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

        # calculate unit normal vector w.r.t. the surface
        ux = cos(cc.alpharad) * cos(np.deg2rad(self.thetadeg))
        uy = cos(cc.alpharad) * sin(np.deg2rad(self.thetadeg))
        uz = sin(cc.alpharad)
        # It would be nicer to calculate this based on e.g. MSI amplitude
        max_imp = 10
        r_TOL = 0.1  # Radius of cylinder to search
        pt1 = (self.x + max_imp * ux, self.y + max_imp * uy,
               self.z + max_imp * uz)
        pt2 = (self.x - max_imp * ux, self.y - max_imp * uy,
               self.z - max_imp * uz)
        # Search for our node in a cylinder normal to the surface, because
        # 'our' node may be moved by a MSI
        nodes = nodes.getByBoundingCylinder(pt1, pt2, r_TOL)
        if len(nodes) != 1:
            warn("Unable to locate node where perturbation load" +
                 "'{0}' is applied. ".format(self.name) +
                 "Cannot calculate imperfection amplitude.")
            self.amplitude = 0.
            return 0.

        odb = cc.attach_results()
        fo = odb.steps[cc.step1Name].frames[-1].fieldOutputs
        if not 'U' in fo.keys():
            raise RuntimeError('Field output '
                               U' not available to calculate amplitude')
        #TODO not sure if this is robust: node.label-1
        u, v, w = fo['U'].values[nodes[0].label - 1].data
        cc.detach_results(odb)

        alpha = cc.alpharad
        theta = np.deg2rad(self.thetadeg)
        amp = -(
            (u * cos(theta) + v * sin(theta)) * cos(alpha) + w * sin(alpha))
        self.amplitude = amp

        return amp
示例#6
0
 def rebuild(self):
     cc = self.impconf.conecyl
     alpharad = np.deg2rad(cc.alphadeg)
     self.cbradial = self.cbtotal*cos(alpharad)
     self.cbmeridional = self.cbtotal*sin(alpharad)
     self.x, self.y, self.z = self.get_xyz()
     self.r, z = cc.r_z_from_pt(self.pt)
     self.thetadeg = self.thetadeg % 360.
     self.thetadegs = [self.thetadeg]
     self.pts = [self.pt]
     self.name = 'CB_pt_{0:03d}_theta_{1:03d}'.format(
                     int(self.pt*100), int(self.thetadeg))
     if abs(self.cbtotal) < 0.1*TOL:
         warn('Ignoring perturbation buckle: {0}'.format(self.name))
示例#7
0
文件: cb.py 项目: desicos/desicos
 def rebuild(self):
     cc = self.impconf.conecyl
     alpharad = np.deg2rad(cc.alphadeg)
     self.cbradial = self.cbtotal*cos(alpharad)
     self.cbmeridional = self.cbtotal*sin(alpharad)
     self.x, self.y, self.z = self.get_xyz()
     self.r, z = cc.r_z_from_pt(self.pt)
     self.thetadeg = self.thetadeg % 360.
     self.thetadegs = [self.thetadeg]
     self.pts = [self.pt]
     self.name = 'CB_pt_{0:03d}_theta_{1:03d}'.format(
                     int(self.pt*100), int(self.thetadeg))
     if abs(self.cbtotal) < 0.1*TOL:
         warn('Ignoring perturbation buckle: {0}'.format(self.name))
示例#8
0
    def calc_amplitude(self):
        """Calculates the geometric imperfection of the finite element model

        .. note:: Must be called from Abaqus.

        Returns
        -------
        max_amp : float
            The maximum absolute amplitude.

        """
        if self.created:
            return calc_msi_amplitude(self.impconf.conecyl, force=True)
        else:
            warn('Mid-surface imperfection not created')
示例#9
0
    def calc_amplitude(self):
        """Calculates the geometric imperfection of the finite element model

        .. note:: Must be called from Abaqus.

        Returns
        -------
        max_amp : float
            The maximum absolute amplitude.

        """
        if self.created:
            return calc_msi_amplitude(self.impconf.conecyl, force=True)
        else:
            warn('Mid-surface imperfection not created')
示例#10
0
 def rebuild(self):
     cc = self.impconf.conecyl
     alpharad = cc.alpharad
     self.plradial = self.pltotal*cos(alpharad)
     self.plz = -self.pltotal*sin(alpharad)
     self.plx = -self.plradial*cos(np.deg2rad(self.thetadeg))
     self.ply = -self.plradial*sin(np.deg2rad(self.thetadeg))
     self.x, self.y, self.z = self.get_xyz()
     self.r, z = cc.r_z_from_pt(self.pt)
     self.thetadeg = self.thetadeg % 360.
     self.thetadegs = [self.thetadeg]
     self.pts = [self.pt]
     self.name = 'PL_pt_{0:03d}_theta_{1:03d}'.format(
                     int(self.pt*100), int(self.thetadeg))
     if abs(self.pltotal) < 0.1*TOL:
         warn('Ignoring perturbation load: {0}'.format(self.name))
示例#11
0
文件: pload.py 项目: desicos/desicos
 def rebuild(self):
     cc = self.impconf.conecyl
     alpharad = cc.alpharad
     self.plradial = self.pltotal*cos(alpharad)
     self.plz = -self.pltotal*sin(alpharad)
     self.plx = -self.plradial*cos(np.deg2rad(self.thetadeg))
     self.ply = -self.plradial*sin(np.deg2rad(self.thetadeg))
     self.x, self.y, self.z = self.get_xyz()
     self.r, z = cc.r_z_from_pt(self.pt)
     self.thetadeg = self.thetadeg % 360.
     self.thetadegs = [self.thetadeg]
     self.pts = [self.pt]
     self.name = 'PL_pt_{0:03d}_theta_{1:03d}'.format(
                     int(self.pt*100), int(self.thetadeg))
     if abs(self.pltotal) < 0.1*TOL:
         warn('Ignoring perturbation load: {0}'.format(self.name))
示例#12
0
文件: pload.py 项目: desicos/desicos
    def calc_amplitude(self):
        """Calculate the imperfection amplitude.

        The odb must be available and it will be used to extract the last
        frame of the first analysis step, corresponding to the constant loads.

        """
        from abaqus import mdb

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

        # calculate unit normal vector w.r.t. the surface
        ux = cos(cc.alpharad)*cos(np.deg2rad(self.thetadeg))
        uy = cos(cc.alpharad)*sin(np.deg2rad(self.thetadeg))
        uz = sin(cc.alpharad)
         # It would be nicer to calculate this based on e.g. MSI amplitude
        max_imp = 10
        r_TOL = 0.1 # Radius of cylinder to search
        pt1 = (self.x + max_imp*ux, self.y + max_imp*uy, self.z + max_imp*uz)
        pt2 = (self.x - max_imp*ux, self.y - max_imp*uy, self.z - max_imp*uz)
        # Search for our node in a cylinder normal to the surface, because
        # 'our' node may be moved by a MSI
        nodes = nodes.getByBoundingCylinder(pt1, pt2, r_TOL)
        if len(nodes) != 1:
            warn("Unable to locate node where perturbation load" +
                 "'{0}' is applied. ".format(self.name) +
                 "Cannot calculate imperfection amplitude.")
            self.amplitude = 0.
            return 0.

        odb = cc.attach_results()
        fo = odb.steps[cc.step1Name].frames[-1].fieldOutputs
        if not 'U' in fo.keys():
            raise RuntimeError(
                    'Field output 'U' not available to calculate amplitude')
        #TODO not sure if this is robust: node.label-1
        u, v, w = fo['U'].values[nodes[0].label-1].data
        cc.detach_results(odb)

        alpha = cc.alpharad
        theta = np.deg2rad(self.thetadeg)
        amp = -((u*cos(theta) + v*sin(theta))*cos(alpha) + w*sin(alpha))
        self.amplitude = amp

        return amp
示例#13
0
    def create_model(self, force=False):
        """Triggers the routines to create the model in Abaqus

        The auxiliary module ``_create_model.py`` is used, from where the
        functions ``_create_mesh()``, ``_create_load_steps()`` and
        ``_create_loads_bcs()`` are executed in this order.

        .. note:: Must be called from Abaqus

        .. note:: When new functionalities have to be implemented or for any
                  debugging purposes, one can conveniently change file
                  ``_create_model.py`` directly, and using the ``__main__``
                  section at the end of this file makes it easy to test
                  whatever necessary methods. The tests can be repeatedly run
                  doing::

                      import os

                      from desicos.abaqus.constants import DAHOME
                      os.chdir(os.path.join(DAHOME, 'conecyl'))
                      execfile('_create_model.py')

        Parameters
        ----------
        force : bool, optional
            Forces the model creation even if the finite element model
            corresponding to this :class:`ConeCyl` object already exists.

        """
        if self.created_model and not force:
            warn('Finite element model already created')
            warn('use "force=True" in order to proceed', level=1)
            return

        self.rebuild()
        from _create_model import (_create_mesh, _create_load_steps,
                                   _create_loads_bcs)

        _create_mesh(self)
        _create_load_steps(self)
        _create_loads_bcs(self)
        self.created_model = True
示例#14
0
    def create_model(self, force=False):
        """Triggers the routines to create the model in Abaqus

        The auxiliary module ``_create_model.py`` is used, from where the
        functions ``_create_mesh()``, ``_create_load_steps()`` and
        ``_create_loads_bcs()`` are executed in this order.

        .. note:: Must be called from Abaqus

        .. note:: When new functionalities have to be implemented or for any
                  debugging purposes, one can conveniently change file
                  ``_create_model.py`` directly, and using the ``__main__``
                  section at the end of this file makes it easy to test
                  whatever necessary methods. The tests can be repeatedly run
                  doing::

                      import os

                      from desicos.abaqus.constants import DAHOME
                      os.chdir(os.path.join(DAHOME, 'conecyl'))
                      execfile('_create_model.py')

        Parameters
        ----------
        force : bool, optional
            Forces the model creation even if the finite element model
            corresponding to this :class:`ConeCyl` object already exists.

        """
        if self.created_model and not force:
            warn('Finite element model already created')
            warn('use "force=True" in order to proceed', level=1)
            return

        self.rebuild()
        from _create_model import (_create_mesh, _create_load_steps,
                                   _create_loads_bcs)

        _create_mesh(self)
        _create_load_steps(self)
        _create_loads_bcs(self)
        self.created_model = True
示例#15
0
    def _update_material(self, suffix, scaling_factor):
        from abaqus import mdb

        cc = self.impconf.conecyl
        mod = mdb.models[cc.model_name]

        warned = set()
        for name, laminaprop in zip(cc.laminapropKeys, cc.laminaprops):
            if len(laminaprop) == 6:
                new_laminaprop = self.calc_scaled_laminaprop(laminaprop, scaling_factor)
            else:
                if name not in warned:
                    warn(('Invalid number of lamina properties for material' +
                        '{0}, or material is isotropic. Fiber Fraction' +
                        ' Imperfection is not applied.').format(name))
                    warned.add(name)
                new_laminaprop = laminaprop
            new_mat = mod.Material(name=(name + suffix),
                                   objectToCopy=mod.materials[name])
            new_mat.elastic.setValues(table=(new_laminaprop,))
示例#16
0
文件: ffi.py 项目: sovsep/desicos
    def _update_material(self, suffix, scaling_factor):
        from abaqus import mdb

        cc = self.impconf.conecyl
        mod = mdb.models[cc.model_name]

        warned = set()
        for name, laminaprop in zip(cc.laminapropKeys, cc.laminaprops):
            if len(laminaprop) == 6:
                new_laminaprop = self.calc_scaled_laminaprop(
                    laminaprop, scaling_factor)
            else:
                if name not in warned:
                    warn(('Invalid number of lamina properties for material' +
                          '{0}, or material is isotropic. Fiber Fraction' +
                          ' Imperfection is not applied.').format(name))
                    warned.add(name)
                new_laminaprop = laminaprop
            new_mat = mod.Material(name=(name + suffix),
                                   objectToCopy=mod.materials[name])
            new_mat.elastic.setValues(table=(new_laminaprop, ))
示例#17
0
    def attach_results(self):
        """Attach the odb file into Abaqus

        If the odb file exists it will be attached in ``session.odbs``, in
        Abaqus.

        .. note:: Must be called from Abaqus

        """
        import abaqus

        odbname = self.model_name + '.odb'
        odbpath = os.path.join(self.output_dir, odbname)
        if not os.path.isfile(odbpath):
            warn('result was not found')
            return False
        session = abaqus.session
        if not odbpath in session.odbs.keys():
            return session.openOdb(name=odbname, path=odbpath, readOnly=True)
        else:
            return session.odbs[odbname]
示例#18
0
    def attach_results(self):
        """Attach the odb file into Abaqus

        If the odb file exists it will be attached in ``session.odbs``, in
        Abaqus.

        .. note:: Must be called from Abaqus

        """
        import abaqus

        odbname = self.model_name + '.odb'
        odbpath = os.path.join(self.output_dir, odbname)
        if not os.path.isfile(odbpath):
            warn('result was not found')
            return False
        session = abaqus.session
        if not odbpath in session.odbs.keys():
            return session.openOdb(name=odbname, path=odbpath, readOnly=True)
        else:
            return session.odbs[odbname]
示例#19
0
    def check_completed(self, wait=False, print_found=False):
        if not self.rebuilt:
            self.rebuild()
        tmp = os.path.join(self.output_dir, self.model_name + '.log')
        if wait == True:
            log('Waiting for job completion...')
        #TODO a general function to check the log file
        while True:
            if os.path.isfile(tmp):
                tmpfile = open(tmp, 'r')
                lines = tmpfile.readlines()
                tmpfile.close()
                if len(lines) == 0:
                    continue
                if len(lines) < 2:
                    continue
                if lines[-2].find('End Abaqus/Standard Analysis') > -1:
                    if print_found:
                        log('RUN COMPLETED for model {0}'.format(
                            self.model_name))
                    return True
                elif lines[-1].find('Abaqus/Analysis exited with errors') > -1:
                    if print_found:
                        log('RUN COMPLETED WITH ERRORS for model {0}'.format(
                            self.model_name))
                    return True

                else:
                    if not wait:
                        warn('RUN NOT COMPLETED for model {0}'.format(
                            self.model_name))
                        return False
            else:
                if not wait:
                    warn('RUN NOT STARTED for model {0}'.format(
                        self.model_name))
                    return False
            if wait:
                import time
                time.sleep(5)
示例#20
0
    def check_completed(self, wait=False, print_found=False):
        if not self.rebuilt:
            self.rebuild()
        tmp = os.path.join(self.output_dir, self.model_name + '.log')
        if wait == True:
            log('Waiting for job completion...')
        #TODO a general function to check the log file
        while True:
            if os.path.isfile(tmp):
                tmpfile = open(tmp, 'r')
                lines = tmpfile.readlines()
                tmpfile.close()
                if len(lines) == 0:
                    continue
                if len(lines) < 2:
                    continue
                if lines[-2].find('End Abaqus/Standard Analysis') > -1:
                    if print_found:
                        log('RUN COMPLETED for model {0}'.format(
                            self.model_name))
                    return True
                elif lines[-1].find('Abaqus/Analysis exited with errors') > -1:
                    if print_found:
                        log('RUN COMPLETED WITH ERRORS for model {0}'.format(
                            self.model_name))
                    return True

                else:
                    if not wait:
                        warn('RUN NOT COMPLETED for model {0}'.format(
                             self.model_name))
                        return False
            else:
                if not wait:
                    warn('RUN NOT STARTED for model {0}'.format(
                         self.model_name))
                    return False
            if wait:
                import time
                time.sleep(5)
示例#21
0
    def calc_partitions(self, thetadegs=[], pts=[]):
        """Updates all circumferential and axial positions to partition

        This method reads all the imperfections and collects the
        circumferential positions ``thetadegs`` and the normalized meridional
        positions ``pts`` where partitions should be created. These two lists
        will be used in the routines to create an Abaqus model.

        Parameter
        ---------
        thetadegs : list, optional
            Additional positions where circumferential partitions are desired
        pts : list, optional
            Additional positions where meridional partitions are desired

        """
        thetadegs += [0]
        for imp in self.impconf.imperfections:
            valid = True
            for pt in imp.pts:
                if pt<0 or pt>1.:
                    error('Invalid imperfection: {0}, {1}'.format(imp.index,
                          imp.name))
                    warn('Ignored imperfection: {0}, {1}'.format(imp.index,
                         imp.name))
                    valid = False
                    break
            if valid:
                thetadegs += imp.thetadegs
                pts += imp.pts

        for stringer in self.stringerconf.stringers:
            thetadegs += stringer.thetadegs

        self.thetadegs = sorted(list(set(thetadegs)))
        self.pts = sorted(list(set(pts)))
        return self.thetadegs, self.pts
示例#22
0
    def calc_partitions(self, thetadegs=[], pts=[]):
        """Updates all circumferential and axial positions to partition

        This method reads all the imperfections and collects the
        circumferential positions ``thetadegs`` and the normalized meridional
        positions ``pts`` where partitions should be created. These two lists
        will be used in the routines to create an Abaqus model.

        Parameter
        ---------
        thetadegs : list, optional
            Additional positions where circumferential partitions are desired
        pts : list, optional
            Additional positions where meridional partitions are desired

        """
        thetadegs += [0]
        for imp in self.impconf.imperfections:
            valid = True
            for pt in imp.pts:
                if pt < 0 or pt > 1.:
                    error('Invalid imperfection: {0}, {1}'.format(
                        imp.index, imp.name))
                    warn('Ignored imperfection: {0}, {1}'.format(
                        imp.index, imp.name))
                    valid = False
                    break
            if valid:
                thetadegs += imp.thetadegs
                pts += imp.pts

        for stringer in self.stringerconf.stringers:
            thetadegs += stringer.thetadegs

        self.thetadegs = sorted(list(set(thetadegs)))
        self.pts = sorted(list(set(pts)))
        return self.thetadegs, self.pts
示例#23
0
文件: cutout.py 项目: sovsep/desicos
    def create(self):
        from abaqus import mdb
        from abaqusConstants import (SIDE1, SUPERIMPOSE, COPLANAR_EDGES,
                                     MIDDLE, XZPLANE, SWEEP, FIXED)
        from regionToolset import Region

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

        ra = mod.rootAssembly
        datums = p.datums
        d = self.d
        r, z = cc.r_z_from_pt(self.pt)
        x, y, z = self.x, self.y, self.z
        alpharad = cc.alpharad
        drill_offset_rad = np.deg2rad(self.drill_offset_deg)
        thetarad = np.deg2rad(self.thetadeg)
        thetadeg = self.thetadeg
        thetadeg1 = self.thetadeg1
        thetadeg2 = self.thetadeg2

        # line defining the z axis
        _p1 = p.DatumPointByCoordinate(coords=(0, 0, 0))
        _p2 = p.DatumPointByCoordinate(coords=(0, 0, 1))
        zaxis = p.DatumAxisByTwoPoint(point1=datums[_p1.id],
                                      point2=datums[_p2.id])

        # line defining the cutting axis
        self.p1coord = np.array((x, y, z))
        dx = d * cos(alpharad - drill_offset_rad) * cos(thetarad)
        dy = d * cos(alpharad - drill_offset_rad) * sin(thetarad)
        dz = d * sin(alpharad - drill_offset_rad)
        self.p0coord = np.array((x - dx, y - dy, z - dz))
        self.p2coord = np.array((x + dx, y + dy, z + dz))
        p1 = p.DatumPointByCoordinate(coords=self.p1coord)
        p2 = p.DatumPointByCoordinate(coords=self.p2coord)
        drillaxis = p.DatumAxisByTwoPoint(point1=datums[p1.id],
                                          point2=datums[p2.id])

        #TODO get vertices where to pass the cutting plane
        plow = self.p1coord.copy()
        pup = self.p1coord.copy()
        rlow, zlow = cc.r_z_from_pt(self.ptlow)
        plow[2] = zlow
        rup, zup = cc.r_z_from_pt(self.ptup)
        pup[2] = zup

        diag1pt = p.DatumPointByCoordinate(coords=cyl2rec(rup, thetadeg2, zup))
        diag2pt = p.DatumPointByCoordinate(coords=cyl2rec(rup, thetadeg1, zup))
        diag3pt = p.DatumPointByCoordinate(
            coords=cyl2rec(rlow, thetadeg1, zlow))
        diag4pt = p.DatumPointByCoordinate(
            coords=cyl2rec(rlow, thetadeg2, zlow))
        diag1 = p.DatumPlaneByThreePoints(point1=datums[p1.id],
                                          point2=datums[p2.id],
                                          point3=datums[diag1pt.id])
        diag2 = p.DatumPlaneByThreePoints(point1=datums[p1.id],
                                          point2=datums[p2.id],
                                          point3=datums[diag2pt.id])
        diag3 = p.DatumPlaneByThreePoints(point1=datums[p1.id],
                                          point2=datums[p2.id],
                                          point3=datums[diag3pt.id])
        diag4 = p.DatumPlaneByThreePoints(point1=datums[p1.id],
                                          point2=datums[p2.id],
                                          point3=datums[diag4pt.id])

        c1 = cyl2rec(0.5 * (rup + r), thetadeg + 0.5 * self.offsetdeg,
                     0.5 * (z + zup))
        c2 = cyl2rec(0.5 * (rup + r), thetadeg - 0.5 * self.offsetdeg,
                     0.5 * (z + zup))
        c3 = cyl2rec(0.5 * (rlow + r), thetadeg - 0.5 * self.offsetdeg,
                     0.5 * (z + zlow))
        c4 = cyl2rec(0.5 * (rlow + r), thetadeg + 0.5 * self.offsetdeg,
                     0.5 * (z + zlow))

        #TODO try / except blocks needed due to an Abaqus bug
        try:
            face1 = p.faces.findAt(c1)
            p.PartitionFaceByDatumPlane(datumPlane=datums[diag1.id],
                                        faces=face1)
        except:
            pass

        try:
            face2 = p.faces.findAt(c2)
            p.PartitionFaceByDatumPlane(datumPlane=datums[diag2.id],
                                        faces=face2)
        except:
            pass

        try:
            face3 = p.faces.findAt(c3)
            p.PartitionFaceByDatumPlane(datumPlane=datums[diag3.id],
                                        faces=face3)
        except:
            pass

        try:
            face4 = p.faces.findAt(c4)
            p.PartitionFaceByDatumPlane(datumPlane=datums[diag4.id],
                                        faces=face4)
        except:
            pass

        sketchplane = p.DatumPlaneByPointNormal(point=datums[p2.id],
                                                normal=datums[drillaxis.id])

        sketchstrans = p.MakeSketchTransform(
            sketchPlane=datums[sketchplane.id],
            sketchUpEdge=datums[zaxis.id],
            sketchPlaneSide=SIDE1,
            origin=self.p2coord)

        sketch = mod.ConstrainedSketch(name='__profile__',
                                       sheetSize=10. * d,
                                       gridSpacing=d / 10.,
                                       transform=sketchstrans)
        sketch.setPrimaryObject(option=SUPERIMPOSE)
        p.projectReferencesOntoSketch(sketch=sketch, filter=COPLANAR_EDGES)
        sketch.CircleByCenterPerimeter(center=(0.0, 0), point1=(0.0, d / 2.))

        #TODO try / except blocks needed due to an Abaqus bug
        try:
            p.PartitionFaceBySketchDistance(sketchPlane=datums[sketchplane.id],
                                            sketchUpEdge=datums[zaxis.id],
                                            faces=p.faces,
                                            sketchPlaneSide=SIDE1,
                                            sketch=sketch,
                                            distance=1.5 * d)
        except:
            pass

        sketch.unsetPrimaryObject()
        del mod.sketches['__profile__']

        while True:
            faceList = [
                f[0]
                for f in p.faces.getClosest(coordinates=((x, y, z), ),
                                            searchTolerance=(d / 2. -
                                                             0.5)).values()
            ]
            if not faceList:
                break
            #TODO try / except blocks needed due to an Abaqus bug
            try:
                p.RemoveFaces(faceList=faceList, deleteCells=False)
            except:
                pass

        # Seed edges around cutout area
        numel_per_edge = int(np.ceil(self.offsetdeg / 360.0 * cc.numel_r))
        edge_coords = [
            (rup, 0.5 * (thetadeg1 + thetadeg), zup),
            (rup, 0.5 * (thetadeg2 + thetadeg), zup),
            (rlow, 0.5 * (thetadeg1 + thetadeg), zlow),
            (rlow, 0.5 * (thetadeg2 + thetadeg), zlow),
            (0.5 * (rlow + r), thetadeg1, 0.5 * (zlow + z)),
            (0.5 * (rup + r), thetadeg1, 0.5 * (zup + z)),
            (0.5 * (rlow + r), thetadeg2, 0.5 * (zlow + z)),
            (0.5 * (rup + r), thetadeg2, 0.5 * (zup + z)),
        ]
        edge_coords = [cyl2rec(*c) for c in edge_coords]
        edgeList = [
            e[0] for e in p.edges.getClosest(coordinates=edge_coords,
                                             searchTolerance=1.).values()
        ]
        p.seedEdgeByNumber(edges=edgeList,
                           number=numel_per_edge,
                           constraint=FIXED)

        # Seed radial edges about the cutout
        edge_coords = [
            (r, 0.5 * (thetadeg2 + thetadeg), z),
            (0.5 * (rup + r), 0.5 * (thetadeg2 + thetadeg), 0.5 * (zup + z)),
            (0.5 * (rup + r), thetadeg, 0.5 * (zup + z)),
            (0.5 * (rup + r), 0.5 * (thetadeg1 + thetadeg), 0.5 * (zup + z)),
            (r, 0.5 * (thetadeg1 + thetadeg), z),
            (0.5 * (rlow + r), 0.5 * (thetadeg1 + thetadeg), 0.5 * (zlow + z)),
            (0.5 * (rlow + r), thetadeg, 0.5 * (zlow + z)),
            (0.5 * (rlow + r), 0.5 * (thetadeg2 + thetadeg), 0.5 * (zlow + z)),
        ]
        edge_coords = [cyl2rec(*c) for c in edge_coords]
        edgeList = [
            e[0] for e in p.edges.getClosest(coordinates=edge_coords,
                                             searchTolerance=1.).values()
        ]
        p.seedEdgeByNumber(edges=edgeList,
                           number=self.numel_radial_edge,
                           constraint=FIXED)

        # Mesh control for cutout faces
        try:
            p.setMeshControls(regions=p.faces, technique=SWEEP)
        except:
            warn(
                "Unable to set mesh control to 'SWEEP', please check the mesh around your cutout(s)"
            )
        p.generateMesh()
        for pload in cc.impconf.ploads:
            if (pload.pt == self.pt and pload.thetadeg == self.thetadeg
                    and pload.name in mod.loads.keys()):
                warn(
                    "Cutout is in the same location as perturbation load, moving PL to cutout edge"
                )
                inst_shell = ra.instances['INST_SHELL']
                coords = cyl2rec(r, thetadeg + np.rad2deg(self.d / 2. / r), z)
                new_vertex = inst_shell.vertices.getClosest(
                    coordinates=[coords], searchTolerance=1.).values()[0][0]
                #TODO Unfortunately you cannot simply pass a vertex or list of vertices
                # It has to be some internal abaqus sequence type... work around that:
                index = inst_shell.vertices.index(new_vertex)
                region = Region(vertices=inst_shell.vertices[index:index + 1])
                mod.loads[pload.name].setValues(region=region)

        if self.prop_around_cutout is not None:
            self.create_prop_around_cutout()
示例#24
0
def read_file(file_name,
              frequency=1,
              forced_average_radius=None,
              H_measured=None,
              R_best_fit=None,
              stretch_H=False,
              z_offset_bot=None,
              r_TOL=1.):
    log('Reading imperfection file: {0} ...'.format(file_name))
    # user warnings
    if stretch_H:
        if z_offset_bot:
            warn('Because of the stretch_H option, ' +
                 'consider setting z_offset_bot to None')
    # reading the imperfection file
    ignore = False
    mps = np.loadtxt(file_name, dtype=FLOAT)
    r = np.sqrt(mps[:, 0]**2 + mps[:, 1]**2)
    # measuring model dimensions
    if R_best_fit is None:
        R_best_fit = np.average(r)
        warn('The cylinder average radius of the measured points ' +
             'assumed to be {0:1.2f}'.format(R_best_fit))
    z_min = mps[:, 2].min()
    z_max = mps[:, 2].max()
    z_center = (z_max + z_min) / 2.
    H_points = (z_max - z_min)
    log('R_best_fit     : {0}'.format(R_best_fit))
    # applying user inputs
    R = R_best_fit
    if forced_average_radius:
        R = forced_average_radius
        log('Forced measured radius: {0}'.format(forced_average_radius))
    H_model = H_points
    if not H_measured:
        H_measured = H_points
        warn('The cylinder height of the measured points assumed ' +
             'to be {0:1.2f}'.format(H_measured))
    # calculating default z_offset_bot
    if not z_offset_bot:
        if stretch_H:
            z_offset_bot = 0.
        else:
            z_offset_bot = (H_measured - H_points) / 2.
    offset_z = z_offset_bot - z_min
    log('H_points       : {0}'.format(H_points))
    log('H_measured     : {0}'.format(H_measured))
    log('z_min          : {0}'.format(z_min))
    log('z_max          : {0}'.format(z_max))
    log('offset_z       : {0}'.format(offset_z))
    r_TOL_min = (R * (1 - r_TOL / 100.))
    r_TOL_max = (R * (1 + r_TOL / 100.))
    cond = np.all(np.array((r > r_TOL_max, r < r_TOL_min)), axis=0)
    skept = mps[cond]
    log('Skipping {0} points'.format(len(skept)))
    mps = mps[np.logical_not(cond)]
    offset_mps = mps.copy()
    offset_mps[:, 2] += offset_z
    norm_mps = offset_mps.copy()
    norm_mps[:, 0] /= R
    norm_mps[:, 1] /= R
    if stretch_H:
        norm_mps[:, 2] /= H_points
    else:
        norm_mps[:, 2] /= H_measured
    return mps, offset_mps, norm_mps
示例#25
0
def calc_nodal_translations(imperfection_file_name, nodes, H_model, H_measured,
                            R_model, R_best_fit, semi_angle, stretch_H,
                            z_offset_bot, rotatedeg, r_TOL, num_closest_points,
                            power_parameter, num_sec_z, sample_size):
    # reading imperfection file
    m, o, mps = read_file(file_name=imperfection_file_name,
                          H_measured=H_measured,
                          R_best_fit=R_best_fit,
                          forced_average_radius=R_best_fit,
                          stretch_H=stretch_H,
                          z_offset_bot=z_offset_bot,
                          r_TOL=r_TOL)

    log('Calculating nodal translations!')
    if sample_size:
        num = mps.shape[0]
        if sample_size < num:
            log('Using sample_size={0}'.format(sample_size), level=1)
            mps = mps[sample(range(num), int(sample_size)), :]
    num_nodes = nodes.shape[0]
    R_top = R_model - np.tan(np.deg2rad(semi_angle)) * H_model
    semi_angle = abs(semi_angle)

    def local_radius(z):
        return R_model + (R_top - R_model) * z / H_model

    mps[:, 2] *= H_model
    if semi_angle < 1.e-6:
        R_local = R_model
    else:
        R_local = local_radius(mps[:, 2])
    thetarads = np.arctan2(mps[:, 1], mps[:, 0])
    if rotatedeg:
        thetarads += np.deg2rad(rotatedeg)
    mps[:, 0] = R_local * np.cos(thetarads)
    mps[:, 1] = R_local * np.sin(thetarads)
    num_sec_z = int(num_sec_z)
    mem_limit = 1024 * 1024 * 1024 * 8 * 2  # 2 GB
    mem_entries = int(mem_limit / 64)  # if float64 is used
    sec_size = int(num_nodes / num_sec_z)
    #TODO better memory control...
    if sec_size**2 * 10 > mem_entries:
        while True:
            num_sec_z += 1
            sec_size = int(num_nodes / num_sec_z)
            if sec_size**2 * 10 <= mem_entries:
                warn('New sec_size {0}'.format(sec_size))
                break
    ncp = num_closest_points
    nodes = nodes[np.argsort(nodes[:, 2])]
    mps = mps[np.argsort(mps[:, 2])]
    nodal_t = np.zeros(nodes.shape, dtype=nodes.dtype)
    limit = int(num_sec_z / 5)
    for i in xrange(num_sec_z + 1):
        i_inf = sec_size * i
        i_sup = sec_size * (i + 1)
        if i % limit == 0:
            log('processed {0:7d} out of {1:7d} entries'.format(
                min(i_sup, num_nodes), num_nodes),
                level=1)
        sub_nodes = nodes[i_inf:i_sup]
        if not np.any(sub_nodes):
            continue
        inf_z = sub_nodes[:, 2].min()
        sup_z = sub_nodes[:, 2].max()
        tol = 0.01
        if i == 0 or i == num_sec_z:
            tol = 0.05
        while True:
            cond1 = mps[:, 2] >= inf_z - tol * H_model
            cond2 = mps[:, 2] <= sup_z + tol * H_model
            cond = np.all(np.array((cond1, cond2)), axis=0)
            sub_mps = mps[cond]
            if not np.any(sub_mps):
                tol += 0.01
            else:
                break
        dist = np.subtract.outer(sub_nodes[:, 0], sub_mps[:, 0])**2
        dist += np.subtract.outer(sub_nodes[:, 1], sub_mps[:, 1])**2
        dist += np.subtract.outer(sub_nodes[:, 2], sub_mps[:, 2])**2
        asort = np.argsort(dist, axis=1)
        lenn = sub_nodes.shape[0]
        lenp = sub_mps.shape[0]
        asort_mesh = asort + np.meshgrid(
            np.arange(lenn) * lenp, np.arange(lenp))[0].transpose()
        # getting the z coordinate of the closest points
        sub_mps_z = np.take(sub_mps[:, 2], asort[:, :ncp])
        # getting the distance of the closest points
        dist_ncp = np.take(dist, asort_mesh[:, :ncp])
        # avoiding division by zero
        dist_ncp[(dist_ncp == 0)] == 1.e-12
        # calculating the radius of the sub-group of measured points
        radius = np.sqrt(sub_mps[:, 0]**2 + sub_mps[:, 1]**2)
        # taking only the radius of the closest points
        radius_ncp = np.take(radius, asort[:, :ncp])
        # weight calculation
        total_weight = np.sum(1. / (dist_ncp**power_parameter), axis=1)
        weight = 1. / (dist_ncp**power_parameter)
        # calculating the local radius for the closest points
        r_local_ncp = local_radius(sub_mps_z)
        # computing the new radius
        r_new = np.sum(radius_ncp * weight / r_local_ncp,
                       axis=1) / total_weight
        r_new *= local_radius(sub_nodes[:, 2])
        #NOTE modified after Regina, Mariano and Saullo decided to use
        #     the imperfection amplitude constant along the whole cone
        #     surface, which represents better the real manufacturing
        #     conditions. In that case the amplitude will be re-scaled
        #     using only  the bottom radius
        # calculating the local radius for the nodes for the new assumption
        r_local_nodes = np.sqrt(sub_nodes[:, 0]**2 + sub_nodes[:, 1]**2)
        # calculating the scaling factor required for the new assumption
        sf = R_model / r_local_nodes
        theta = np.arctan2(sub_nodes[:, 1], sub_nodes[:, 0])
        nodal_t[i_inf : i_sup][:, 0] = \
                (r_new*np.cos(theta) - sub_nodes[:, 0])*sf
        nodal_t[i_inf : i_sup][:, 1] = \
                (r_new*np.sin(theta) - sub_nodes[:, 1])*sf
        nodal_t[i_inf:i_sup][:, 3] = sub_nodes[:, 3]
    nodal_t = nodal_t[np.argsort(nodal_t[:, 3])]
    log('Nodal translations calculated!')

    return nodal_t
示例#26
0
    def create(self):
        from abaqus import mdb
        from abaqusConstants import SIDE1, SUPERIMPOSE, COPLANAR_EDGES, MIDDLE, XZPLANE, SWEEP, FIXED
        from regionToolset import Region

        cc = self.impconf.conecyl
        mod = mdb.models[cc.model_name]
        p = mod.parts[cc.part_name_shell]
        ra = mod.rootAssembly
        datums = p.datums
        self.part = p
        d = self.d
        r, z = cc.r_z_from_pt(self.pt)
        x, y, z = self.x, self.y, self.z
        alpharad = cc.alpharad
        drill_offset_rad = np.deg2rad(self.drill_offset_deg)
        thetarad = np.deg2rad(self.thetadeg)
        thetadeg = self.thetadeg
        thetadeg1 = self.thetadeg1
        thetadeg2 = self.thetadeg2

        # line defining the z axis
        _p1 = p.DatumPointByCoordinate(coords=(0, 0, 0))
        _p2 = p.DatumPointByCoordinate(coords=(0, 0, 1))
        zaxis = p.DatumAxisByTwoPoint(point1=datums[_p1.id], point2=datums[_p2.id])

        # line defining the cutting axis
        self.p1coord = np.array((x, y, z))
        dx = d * cos(alpharad - drill_offset_rad) * cos(thetarad)
        dy = d * cos(alpharad - drill_offset_rad) * sin(thetarad)
        dz = d * sin(alpharad - drill_offset_rad)
        self.p0coord = np.array((x - dx, y - dy, z - dz))
        self.p2coord = np.array((x + dx, y + dy, z + dz))
        p1 = p.DatumPointByCoordinate(coords=self.p1coord)
        p2 = p.DatumPointByCoordinate(coords=self.p2coord)
        drillaxis = p.DatumAxisByTwoPoint(point1=datums[p1.id], point2=datums[p2.id])

        # TODO get vertices where to pass the cutting plane
        plow = self.p1coord.copy()
        pup = self.p1coord.copy()
        rlow, zlow = cc.r_z_from_pt(self.ptlow)
        plow[2] = zlow
        rup, zup = cc.r_z_from_pt(self.ptup)
        pup[2] = zup

        diag1pt = p.DatumPointByCoordinate(coords=cyl2rec(rup, thetadeg2, zup))
        diag2pt = p.DatumPointByCoordinate(coords=cyl2rec(rup, thetadeg1, zup))
        diag3pt = p.DatumPointByCoordinate(coords=cyl2rec(rlow, thetadeg1, zlow))
        diag4pt = p.DatumPointByCoordinate(coords=cyl2rec(rlow, thetadeg2, zlow))
        diag1 = p.DatumPlaneByThreePoints(point1=datums[p1.id], point2=datums[p2.id], point3=datums[diag1pt.id])
        diag2 = p.DatumPlaneByThreePoints(point1=datums[p1.id], point2=datums[p2.id], point3=datums[diag2pt.id])
        diag3 = p.DatumPlaneByThreePoints(point1=datums[p1.id], point2=datums[p2.id], point3=datums[diag3pt.id])
        diag4 = p.DatumPlaneByThreePoints(point1=datums[p1.id], point2=datums[p2.id], point3=datums[diag4pt.id])

        c1 = cyl2rec(0.5 * (rup + r), thetadeg + 0.5 * self.offsetdeg, 0.5 * (z + zup))
        c2 = cyl2rec(0.5 * (rup + r), thetadeg - 0.5 * self.offsetdeg, 0.5 * (z + zup))
        c3 = cyl2rec(0.5 * (rlow + r), thetadeg - 0.5 * self.offsetdeg, 0.5 * (z + zlow))
        c4 = cyl2rec(0.5 * (rlow + r), thetadeg + 0.5 * self.offsetdeg, 0.5 * (z + zlow))

        # TODO try / except blocks needed due to an Abaqus bug
        try:
            face1 = p.faces.findAt(c1)
            p.PartitionFaceByDatumPlane(datumPlane=datums[diag1.id], faces=face1)
        except:
            pass

        try:
            face2 = p.faces.findAt(c2)
            p.PartitionFaceByDatumPlane(datumPlane=datums[diag2.id], faces=face2)
        except:
            pass

        try:
            face3 = p.faces.findAt(c3)
            p.PartitionFaceByDatumPlane(datumPlane=datums[diag3.id], faces=face3)
        except:
            pass

        try:
            face4 = p.faces.findAt(c4)
            p.PartitionFaceByDatumPlane(datumPlane=datums[diag4.id], faces=face4)
        except:
            pass

        sketchplane = p.DatumPlaneByPointNormal(point=datums[p2.id], normal=datums[drillaxis.id])

        sketchstrans = p.MakeSketchTransform(
            sketchPlane=datums[sketchplane.id],
            sketchUpEdge=datums[zaxis.id],
            sketchPlaneSide=SIDE1,
            origin=self.p2coord,
        )

        sketch = mod.ConstrainedSketch(
            name="__profile__", sheetSize=10.0 * d, gridSpacing=d / 10.0, transform=sketchstrans
        )
        sketch.setPrimaryObject(option=SUPERIMPOSE)
        p.projectReferencesOntoSketch(sketch=sketch, filter=COPLANAR_EDGES)
        sketch.CircleByCenterPerimeter(center=(0.0, 0), point1=(0.0, d / 2.0))

        # TODO try / except blocks needed due to an Abaqus bug
        try:
            p.PartitionFaceBySketchDistance(
                sketchPlane=datums[sketchplane.id],
                sketchUpEdge=datums[zaxis.id],
                faces=p.faces,
                sketchPlaneSide=SIDE1,
                sketch=sketch,
                distance=1.5 * d,
            )
        except:
            pass

        sketch.unsetPrimaryObject()
        del mod.sketches["__profile__"]

        while True:
            faceList = [
                f[0] for f in p.faces.getClosest(coordinates=((x, y, z),), searchTolerance=(d / 2.0 - 0.5)).values()
            ]
            if not faceList:
                break
            # TODO try / except blocks needed due to an Abaqus bug
            try:
                p.RemoveFaces(faceList=faceList, deleteCells=False)
            except:
                pass

        # Seed edges around cutout area
        numel_per_edge = int(np.ceil(self.offsetdeg / 360.0 * cc.numel_r))
        edge_coords = [
            (rup, 0.5 * (thetadeg1 + thetadeg), zup),
            (rup, 0.5 * (thetadeg2 + thetadeg), zup),
            (rlow, 0.5 * (thetadeg1 + thetadeg), zlow),
            (rlow, 0.5 * (thetadeg2 + thetadeg), zlow),
            (0.5 * (rlow + r), thetadeg1, 0.5 * (zlow + z)),
            (0.5 * (rup + r), thetadeg1, 0.5 * (zup + z)),
            (0.5 * (rlow + r), thetadeg2, 0.5 * (zlow + z)),
            (0.5 * (rup + r), thetadeg2, 0.5 * (zup + z)),
        ]
        edge_coords = [cyl2rec(*c) for c in edge_coords]
        edgeList = [e[0] for e in p.edges.getClosest(coordinates=edge_coords, searchTolerance=1.0).values()]
        p.seedEdgeByNumber(edges=edgeList, number=numel_per_edge, constraint=FIXED)

        # Seed radial edges about the cutout
        edge_coords = [
            (r, 0.5 * (thetadeg2 + thetadeg), z),
            (0.5 * (rup + r), 0.5 * (thetadeg2 + thetadeg), 0.5 * (zup + z)),
            (0.5 * (rup + r), thetadeg, 0.5 * (zup + z)),
            (0.5 * (rup + r), 0.5 * (thetadeg1 + thetadeg), 0.5 * (zup + z)),
            (r, 0.5 * (thetadeg1 + thetadeg), z),
            (0.5 * (rlow + r), 0.5 * (thetadeg1 + thetadeg), 0.5 * (zlow + z)),
            (0.5 * (rlow + r), thetadeg, 0.5 * (zlow + z)),
            (0.5 * (rlow + r), 0.5 * (thetadeg2 + thetadeg), 0.5 * (zlow + z)),
        ]
        edge_coords = [cyl2rec(*c) for c in edge_coords]
        edgeList = [e[0] for e in p.edges.getClosest(coordinates=edge_coords, searchTolerance=1.0).values()]
        p.seedEdgeByNumber(edges=edgeList, number=self.numel_radial_edge, constraint=FIXED)

        # Mesh control for cutout faces
        try:
            p.setMeshControls(regions=p.faces, technique=SWEEP)
        except:
            warn("Unable to set mesh control to 'SWEEP', please check the mesh around your cutout(s)")
        p.generateMesh()
        for pload in cc.impconf.ploads:
            if pload.pt == self.pt and pload.thetadeg == self.thetadeg and pload.name in mod.loads.keys():
                warn("Cutout is in the same location as perturbation load, moving PL to cutout edge")
                inst_shell = ra.instances["INST_SHELL"]
                coords = cyl2rec(r, thetadeg + np.rad2deg(self.d / 2.0 / r), z)
                new_vertex = inst_shell.vertices.getClosest(coordinates=[coords], searchTolerance=1.0).values()[0][0]
                # TODO Unfortunately you cannot simply pass a vertex or list of vertices
                # It has to be some internal abaqus sequence type... work around that:
                index = inst_shell.vertices.index(new_vertex)
                region = Region(vertices=inst_shell.vertices[index : index + 1])
                mod.loads[pload.name].setValues(region=region)
示例#27
0
def read_file(file_name,
               frequency             = 1,
               forced_average_radius = None,
               H_measured            = None,
               R_best_fit            = None,
               stretch_H             = False,
               z_offset_bot            = None,
               r_TOL                 = 1.):
    log('Reading imperfection file: {0} ...'.format(file_name))
    # user warnings
    if stretch_H:
        if z_offset_bot:
            warn('Because of the stretch_H option, '+
                 'consider setting z_offset_bot to None')
    # reading the imperfection file
    ignore = False
    mps = np.loadtxt(file_name, dtype=FLOAT)
    r = np.sqrt(mps[:, 0]**2 + mps[:, 1]**2)
    # measuring model dimensions
    if R_best_fit is None:
        R_best_fit   = np.average(r)
        warn('The cylinder average radius of the measured points ' +
             'assumed to be {0:1.2f}'.format(R_best_fit))
    z_min = mps[:, 2].min()
    z_max = mps[:, 2].max()
    z_center  = (z_max + z_min)/2.
    H_points  = (z_max - z_min)
    log('R_best_fit     : {0}'.format(R_best_fit))
    # applying user inputs
    R = R_best_fit
    if forced_average_radius:
        R = forced_average_radius
        log('Forced measured radius: {0}'.format(forced_average_radius))
    H_model = H_points
    if not H_measured:
        H_measured = H_points
        warn('The cylinder height of the measured points assumed ' +
             'to be {0:1.2f}'.format(H_measured))
    # calculating default z_offset_bot
    if not z_offset_bot:
        if stretch_H:
            z_offset_bot = 0.
        else:
            z_offset_bot = (H_measured - H_points) / 2.
    offset_z = z_offset_bot - z_min
    log('H_points       : {0}'.format(H_points))
    log('H_measured     : {0}'.format(H_measured))
    log('z_min          : {0}'.format(z_min))
    log('z_max          : {0}'.format(z_max))
    log('offset_z       : {0}'.format(offset_z))
    r_TOL_min = (R * (1-r_TOL/100.))
    r_TOL_max = (R * (1+r_TOL/100.))
    cond = np.all(np.array((r > r_TOL_max,
                            r < r_TOL_min)), axis=0)
    skept = mps[cond]
    log('Skipping {0} points'.format(len(skept)))
    mps = mps[np.logical_not(cond)]
    offset_mps = mps.copy()
    offset_mps[:, 2] += offset_z
    norm_mps = offset_mps.copy()
    norm_mps[:, 0] /= R
    norm_mps[:, 1] /= R
    if stretch_H:
        norm_mps[:, 2] /= H_points
    else:
        norm_mps[:, 2] /= H_measured
    return mps, offset_mps, norm_mps
示例#28
0
def calc_nodal_translations(imperfection_file_name,
                            nodes,
                            H_model,
                            H_measured,
                            R_model,
                            R_best_fit,
                            semi_angle,
                            stretch_H,
                            z_offset_bot,
                            rotatedeg,
                            r_TOL,
                            num_closest_points,
                            power_parameter,
                            num_sec_z,
                            sample_size):
    # reading imperfection file
    m, o, mps = read_file(file_name = imperfection_file_name,
                          H_measured = H_measured,
                          R_best_fit = R_best_fit,
                          forced_average_radius = R_best_fit,
                          stretch_H = stretch_H,
                          z_offset_bot = z_offset_bot,
                          r_TOL = r_TOL)

    log('Calculating nodal translations!')
    if sample_size:
        num = mps.shape[0]
        if sample_size < num:
            log('Using sample_size={0}'.format(sample_size), level=1)
            mps = mps[sample(range(num), int(sample_size)), :]
    num_nodes = nodes.shape[0]
    R_top = R_model - np.tan(np.deg2rad(semi_angle)) * H_model
    semi_angle = abs(semi_angle)
    def local_radius(z):
        return R_model + (R_top - R_model) * z / H_model
    mps[:, 2] *= H_model
    if semi_angle < 1.e-6:
        R_local = R_model
    else:
        R_local = local_radius(mps[:, 2])
    thetarads = np.arctan2(mps[:, 1], mps[:, 0])
    if rotatedeg:
        thetarads += np.deg2rad(rotatedeg)
    mps[:, 0] = R_local*np.cos(thetarads)
    mps[:, 1] = R_local*np.sin(thetarads)
    num_sec_z = int(num_sec_z)
    mem_limit = 1024*1024*1024*8*2    # 2 GB
    mem_entries = int(mem_limit / 64) # if float64 is used
    sec_size = int(num_nodes/num_sec_z)
    #TODO better memory control...
    if sec_size**2*10 > mem_entries:
        while True:
            num_sec_z +=1
            sec_size = int(num_nodes/num_sec_z)
            if sec_size**2*10 <= mem_entries:
                warn('New sec_size {0}'.format(sec_size))
                break
    ncp = num_closest_points
    nodes = nodes[np.argsort(nodes[:, 2])]
    mps = mps[np.argsort(mps[:, 2])]
    nodal_t = np.zeros(nodes.shape, dtype=nodes.dtype)
    limit = int(num_sec_z/5)
    for i in xrange(num_sec_z+1):
        i_inf = sec_size*i
        i_sup = sec_size*(i+1)
        if i % limit == 0:
            log('processed {0:7d} out of {1:7d} entries'.format(
                min(i_sup, num_nodes), num_nodes), level=1)
        sub_nodes = nodes[i_inf : i_sup]
        if not np.any(sub_nodes):
            continue
        inf_z = sub_nodes[:, 2].min()
        sup_z = sub_nodes[:, 2].max()
        tol = 0.01
        if i == 0 or i == num_sec_z:
            tol = 0.05
        while True:
            cond1 = mps[:, 2] >= inf_z - tol*H_model
            cond2 = mps[:, 2] <= sup_z + tol*H_model
            cond = np.all(np.array((cond1, cond2)), axis=0)
            sub_mps = mps[cond]
            if not np.any(sub_mps):
                tol += 0.01
            else:
                break
        dist  = np.subtract.outer(sub_nodes[:, 0], sub_mps[:, 0])**2
        dist += np.subtract.outer(sub_nodes[:, 1], sub_mps[:, 1])**2
        dist += np.subtract.outer(sub_nodes[:, 2], sub_mps[:, 2])**2
        asort = np.argsort(dist, axis=1)
        lenn = sub_nodes.shape[0]
        lenp = sub_mps.shape[0]
        asort_mesh = asort + np.meshgrid(np.arange(lenn)*lenp,
                                         np.arange(lenp))[0].transpose()
        # getting the z coordinate of the closest points
        sub_mps_z = np.take(sub_mps[:, 2], asort[:, :ncp])
        # getting the distance of the closest points
        dist_ncp = np.take(dist, asort_mesh[:, :ncp])
        # avoiding division by zero
        dist_ncp[(dist_ncp==0)] == 1.e-12
        # calculating the radius of the sub-group of measured points
        radius = np.sqrt(sub_mps[:, 0]**2 + sub_mps[:, 1]**2)
        # taking only the radius of the closest points
        radius_ncp = np.take(radius, asort[:, :ncp])
        # weight calculation
        total_weight = np.sum(1./(dist_ncp**power_parameter), axis=1)
        weight = 1./(dist_ncp**power_parameter)
        # calculating the local radius for the closest points
        r_local_ncp = local_radius(sub_mps_z)
        # computing the new radius
        r_new = np.sum(radius_ncp*weight/r_local_ncp, axis=1)/total_weight
        r_new *= local_radius(sub_nodes[:, 2])
        #NOTE modified after Regina, Mariano and Saullo decided to use
        #     the imperfection amplitude constant along the whole cone
        #     surface, which represents better the real manufacturing
        #     conditions. In that case the amplitude will be re-scaled
        #     using only  the bottom radius
        # calculating the local radius for the nodes for the new assumption
        r_local_nodes = np.sqrt(sub_nodes[:,0]**2 + sub_nodes[:, 1]**2)
        # calculating the scaling factor required for the new assumption
        sf = R_model/r_local_nodes
        theta = np.arctan2(sub_nodes[:, 1], sub_nodes[:, 0])
        nodal_t[i_inf : i_sup][:, 0] = \
                (r_new*np.cos(theta) - sub_nodes[:, 0])*sf
        nodal_t[i_inf : i_sup][:, 1] = \
                (r_new*np.sin(theta) - sub_nodes[:, 1])*sf
        nodal_t[i_inf : i_sup][:, 3] = sub_nodes[:, 3]
    nodal_t = nodal_t[np.argsort(nodal_t[:, 3])]
    log('Nodal translations calculated!')

    return nodal_t
示例#29
0
    def create(self, force=False):
        """Applies the mid-surface imperfection in the finite element model

        .. note:: Must be called from Abaqus.

        Parameters
        ----------
        force : bool, optional
            Creates the imperfection even when it is already created

        """
        from abaqus import mdb

        if self.created:
            if force:
                self.created = False
                self.create()
            else:
                return
        cc = self.impconf.conecyl
        if self.c0 is None:
            self.nodal_translations = translate_nodes_ABAQUS(
                              imperfection_file_name = self.path,
                              model_name = cc.model_name,
                              part_name = cc.part_name_shell,
                              H_model = cc.H,
                              H_measured = self.H_measured,
                              R_model = cc.rbot,
                              R_best_fit = self.R_best_fit,
                              semi_angle = cc.alphadeg,
                              stretch_H = self.stretch_H,
                              rotatedeg = self.rotatedeg,
                              scaling_factor = self.scaling_factor,
                              r_TOL = self.r_TOL,
                              num_closest_points = self.ncp,
                              power_parameter = self.power_parameter,
                              num_sec_z = self.num_sec_z,
                              nodal_translations = self.nodal_translations,
                              use_theta_z_format = self.use_theta_z_format,
                              ignore_bot_h = self.ignore_bot_h,
                              ignore_top_h = self.ignore_top_h,
                              sample_size = self.sample_size)
        else:
            if self.rotatedeg:
                warn('"rotatedeg != 0", be sure you included this effect ' +
                     'when calculating "c0"')
            self.nodal_translations = translate_nodes_ABAQUS_c0(
                              m0 = self.m0,
                              n0 = self.n0,
                              c0 = self.c0,
                              funcnum = self.funcnum,
                              model_name = cc.model_name,
                              part_name = cc.part_name_shell,
                              H_model = cc.H,
                              semi_angle = cc.alphadeg,
                              scaling_factor = self.scaling_factor,
                              fem_meridian_bot2top = True,
                              ignore_bot_h = self.ignore_bot_h,
                              ignore_top_h = self.ignore_top_h)
        self.created = True
        print '%s amplitude = %f' % (self.name, self.calc_amplitude())

        return self.nodal_translations
示例#30
0
    def rebuild(self, force=False, save_rebuild=True):
        """Updates the properties of the current :class:`.ConeCyl` object

        Parameters
        ----------
        force : bool
            Force the update even if it is already rebuilt (even if
            the ``rebuilt`` attribute is ``True``).
        save_rebuild : bool
            Tells if the ``rebuilt`` attribute should be ``True`` after the
            update.

        """
        if self.rebuilt and not force:
            return

        if self.model_name:
            self.rename = False

        if self.force_output:
            self.output_requests += ['SF']

        if save_rebuild:
            #if len(self.impconf.ploads) == 0:
                #print 'WARNING - separate_load_steps changed to False'
                #self.separate_load_steps = False
            if not self.separate_load_steps:
                self.num_of_steps = 1
            if self.separate_load_steps:
                self.num_of_steps = 2

        # angle in radians
        if self.alphadeg is not None:
            self.alpharad = np.deg2rad(self.alphadeg)

        self.rtop = self.rbot
        if self.rbot is not None and self.H is not None and self.alpharad is not None:
            self.rtop = self.rbot - np.tan(self.alpharad) * self.H
        self.L = self.H/np.cos(self.alpharad)

        # mesh
        self.rmesh = ((self.rbot - self.rtop)*self.rtop/self.rbot + self.rtop)
        self.mesh_size = 2*np.pi*self.rmesh/self.numel_r

        # cutouts
        for cutout in self.cutouts:
            cutout.rebuild()

        # allowables
        if self.allowable and not self.allowables:
            self.allowables = [tuple(self.allowable) for i in self.stack]

        # laminapropKeys
        if not self.laminapropKeys:
            self.laminapropKeys = [self.laminapropKey for i in self.stack]

        # laminaprops
        if not self.laminaprops:
            laminaprops = fetch('laminaprops')
            if self.laminaprop:
                self.laminaprops = [tuple(self.laminaprop) for i in self.stack]
            else:
                self.laminaprops = [laminaprops[k] for k in self.laminapropKeys]

        # ply thicknesses
        if not self.plyts:
            self.plyts = [self.plyt for i in self.stack]
        else:
            if isinstance(self.plyts, list):
                if len(self.plyts) != len(self.stack):
                    self.plyts = [plyts[0] for i in self.stack]
            else:
                self.plyts = [plyts for i in self.stack]

        # calculating ABD matrix
        if self.direct_ABD_input:
            self.calc_ABD_matrix()

        # imperfections
        if self.betadeg:
            self.impconf.uneven_top_edge.betadeg = self.betadeg
            self.impconf.uneven_top_edge.omegadeg = self.omegadeg
        self.impconf.rebuild()

        # model_name
        if self.rename:
            if not self.study:
                tmp = [self.name_DB] + [self.impconf.name]
                self.model_name = '_'.join(tmp)
            else:
                self.model_name = (self.study.name +
                                   '_model_{0:02d}'.format(self.index+1))

        # defining if bottom edge will have GAP elements
        if self.impconf.uneven_bottom_edge:
            self.bc_gaps_bottom_edge = True
        else:
            self.bc_gaps_bottom_edge = False

        # defining if top edge will have GAP elements
        # This is the case if displacment ctrl is used, and either:
        # - the top edge is uneven
        # - the relevant faces are not constrained fully (both uR and v),
        #       so a pin-type MPC cannot be used.
        top_needs_gap = not (self.bc_fix_top_uR and self.bc_fix_top_v)
        side_needs_gap = self.bc_fix_top_side_u3 and not (
            self.bc_fix_top_side_uR and self.bc_fix_top_side_v)
        if not (top_needs_gap or side_needs_gap):
            if self.displ_controlled:
                if self.impconf.uneven_top_edge:
                    self.bc_gaps_top_edge = True
                else:
                    self.bc_gaps_top_edge = False
            else:
                self.bc_gaps_top_edge = False

        else:
            if self.displ_controlled:
                self.bc_gaps_top_edge = True
            else:
                self.bc_gaps_top_edge = False


        if self.linear_buckling:
            self.bc_gaps_bottom_edge = False
            self.bc_gaps_top_edge = False


        if (not self.bc_fix_top_uR or not self.bc_fix_top_v or self.Nxxtop):
            self.distr_load_top = True
        if (not self.linear_buckling and self.impconf.uneven_top_edge
            and self.distr_load_top):
            warn('Distributed load is not compatible with uneven top edge ' +
                 'conditions!')
            warn('Using a concentrated load at the reference point!')
            self.distr_load_top = False

        # Apply DLR boundary conditions
        if self.use_DLR_bc:
            self.resin_add_BIR = True
            self.resin_add_BOR = True
            self.resin_add_TIR = True
            self.resin_add_TOR = True
            self.bc_fix_bottom_side_uR = True
            self.bc_fix_bottom_side_v  = False
            self.bc_fix_bottom_side_u3 = False
            self.bc_fix_top_side_uR    = True
            self.bc_fix_top_side_v     = False
            self.bc_fix_top_side_u3    = False

        if save_rebuild:
            self.rebuilt = True
示例#31
0
    def rebuild(self, force=False, save_rebuild=True):
        """Updates the properties of the current :class:`.ConeCyl` object

        Parameters
        ----------
        force : bool
            Force the update even if it is already rebuilt (even if
            the ``rebuilt`` attribute is ``True``).
        save_rebuild : bool
            Tells if the ``rebuilt`` attribute should be ``True`` after the
            update.

        """
        if self.rebuilt and not force:
            return

        if self.model_name:
            self.rename = False

        if self.force_output:
            self.output_requests += ['SF']

        if save_rebuild:
            #if len(self.impconf.ploads) == 0:
            #print 'WARNING - separate_load_steps changed to False'
            #self.separate_load_steps = False
            if not self.separate_load_steps:
                self.num_of_steps = 1
            if self.separate_load_steps:
                self.num_of_steps = 2

        # angle in radians
        if self.alphadeg is not None:
            self.alpharad = np.deg2rad(self.alphadeg)

        self.rtop = self.rbot
        if self.rbot is not None and self.H is not None and self.alpharad is not None:
            self.rtop = self.rbot - np.tan(self.alpharad) * self.H
        self.L = self.H / np.cos(self.alpharad)

        # mesh
        self.rmesh = ((self.rbot - self.rtop) * self.rtop / self.rbot +
                      self.rtop)
        self.mesh_size = 2 * np.pi * self.rmesh / self.numel_r

        # cutouts
        for cutout in self.cutouts:
            cutout.rebuild()

        # allowables
        if self.allowable and not self.allowables:
            self.allowables = [tuple(self.allowable) for i in self.stack]

        # laminapropKeys
        if not self.laminapropKeys:
            self.laminapropKeys = [self.laminapropKey for i in self.stack]

        # laminaprops
        if not self.laminaprops:
            laminaprops = fetch('laminaprops')
            if self.laminaprop:
                self.laminaprops = [tuple(self.laminaprop) for i in self.stack]
            else:
                self.laminaprops = [
                    laminaprops[k] for k in self.laminapropKeys
                ]

        # ply thicknesses
        if not self.plyts:
            self.plyts = [self.plyt for i in self.stack]
        else:
            if isinstance(self.plyts, list):
                if len(self.plyts) != len(self.stack):
                    self.plyts = [plyts[0] for i in self.stack]
            else:
                self.plyts = [plyts for i in self.stack]

        # calculating ABD matrix
        if self.direct_ABD_input:
            self.calc_ABD_matrix()

        # imperfections
        if self.betadeg:
            self.impconf.uneven_top_edge.betadeg = self.betadeg
            self.impconf.uneven_top_edge.omegadeg = self.omegadeg
        self.impconf.rebuild()

        # model_name
        if self.rename:
            if not self.study:
                tmp = [self.name_DB] + [self.impconf.name]
                self.model_name = '_'.join(tmp)
            else:
                self.model_name = (self.study.name +
                                   '_model_{0:02d}'.format(self.index + 1))

        # defining if bottom edge will have GAP elements
        if self.impconf.uneven_bottom_edge:
            self.bc_gaps_bottom_edge = True
        else:
            self.bc_gaps_bottom_edge = False

        # defining if top edge will have GAP elements
        # This is the case if displacment ctrl is used, and either:
        # - the top edge is uneven
        # - the relevant faces are not constrained fully (both uR and v),
        #       so a pin-type MPC cannot be used.
        top_needs_gap = not (self.bc_fix_top_uR and self.bc_fix_top_v)
        side_needs_gap = self.bc_fix_top_side_u3 and not (
            self.bc_fix_top_side_uR and self.bc_fix_top_side_v)
        if not (top_needs_gap or side_needs_gap):
            if self.displ_controlled:
                if self.impconf.uneven_top_edge:
                    self.bc_gaps_top_edge = True
                else:
                    self.bc_gaps_top_edge = False
            else:
                self.bc_gaps_top_edge = False

        else:
            if self.displ_controlled:
                self.bc_gaps_top_edge = True
            else:
                self.bc_gaps_top_edge = False

        if self.linear_buckling:
            self.bc_gaps_bottom_edge = False
            self.bc_gaps_top_edge = False

        if (not self.bc_fix_top_uR or not self.bc_fix_top_v or self.Nxxtop):
            self.distr_load_top = True
        if (not self.linear_buckling and self.impconf.uneven_top_edge
                and self.distr_load_top):
            warn('Distributed load is not compatible with uneven top edge ' +
                 'conditions!')
            warn('Using a concentrated load at the reference point!')
            self.distr_load_top = False

        # Apply DLR boundary conditions
        if self.use_DLR_bc:
            self.resin_add_BIR = True
            self.resin_add_BOR = True
            self.resin_add_TIR = True
            self.resin_add_TOR = True
            self.bc_fix_bottom_side_uR = True
            self.bc_fix_bottom_side_v = False
            self.bc_fix_bottom_side_u3 = False
            self.bc_fix_top_side_uR = True
            self.bc_fix_top_side_v = False
            self.bc_fix_top_side_u3 = False

        if save_rebuild:
            self.rebuilt = True
示例#32
0
    def create(self, force=False):
        """Applies the mid-surface imperfection in the finite element model

        .. note:: Must be called from Abaqus.

        Parameters
        ----------
        force : bool, optional
            Creates the imperfection even when it is already created

        """
        from abaqus import mdb

        if self.created:
            if force:
                self.created = False
                self.create()
            else:
                return
        cc = self.impconf.conecyl
        if self.c0 is None:
            self.nodal_translations = translate_nodes_ABAQUS(
                              imperfection_file_name = self.path,
                              model_name = cc.model_name,
                              part_name = cc.part_name_shell,
                              H_model = cc.H,
                              H_measured = self.H_measured,
                              R_model = cc.rbot,
                              R_best_fit = self.R_best_fit,
                              semi_angle = cc.alphadeg,
                              stretch_H = self.stretch_H,
                              rotatedeg = self.rotatedeg,
                              scaling_factor = self.scaling_factor,
                              r_TOL = self.r_TOL,
                              num_closest_points = self.ncp,
                              power_parameter = self.power_parameter,
                              num_sec_z = self.num_sec_z,
                              nodal_translations = self.nodal_translations,
                              use_theta_z_format = self.use_theta_z_format,
                              ignore_bot_h = self.ignore_bot_h,
                              ignore_top_h = self.ignore_top_h,
                              sample_size = self.sample_size)
        else:
            if self.rotatedeg:
                warn('"rotatedeg != 0", be sure you included this effect ' +
                     'when calculating "c0"')
            self.nodal_translations = translate_nodes_ABAQUS_c0(
                              m0 = self.m0,
                              n0 = self.n0,
                              c0 = self.c0,
                              funcnum = self.funcnum,
                              model_name = cc.model_name,
                              part_name = cc.part_name_shell,
                              H_model = cc.H,
                              semi_angle = cc.alphadeg,
                              scaling_factor = self.scaling_factor,
                              fem_meridian_bot2top = True,
                              ignore_bot_h = self.ignore_bot_h,
                              ignore_top_h = self.ignore_top_h)
        self.created = True
        print '%s amplitude = %f' % (self.name, self.calc_amplitude())

        return self.nodal_translations