def main():
    import os

    import numpy as nm
    import matplotlib.pyplot as plt

    from sfepy.fem import MeshIO
    import sfepy.linalg as la
    from sfepy.mechanics.contact_bodies import ContactSphere, plot_points

    conf_dir = os.path.dirname(__file__)
    io = MeshIO.any_from_filename(filename_mesh, prefix_dir=conf_dir)
    bb = io.read_bounding_box()
    outline = [vv for vv in la.combine(zip(*bb))]

    ax = plot_points(None, nm.array(outline), 'r*')
    csc = materials['cs'][0]
    cs = ContactSphere(csc['.c'], csc['.r'])

    pps = (bb[1] - bb[0]) * nm.random.rand(5000, 3) + bb[0]
    mask = cs.mask_points(pps, 0.0)

    ax = plot_points(ax, cs.centre[None, :], 'b*', ms=30)
    ax = plot_points(ax, pps[mask], 'kv')
    ax = plot_points(ax, pps[~mask], 'r.')

    plt.show()
示例#2
0
    def get_fargs(self,
                  force_pars,
                  centre,
                  radius,
                  virtual,
                  state,
                  mode=None,
                  term_mode=None,
                  diff_var=None,
                  **kwargs):
        sg, _ = self.get_mapping(virtual)

        assert_((force_pars >= 0.0).all(),
                'force parameters must be non-negative!')

        if self.cs is None:
            self.cs = ContactSphere(centre, radius)

        ig = self.char_fun.ig
        qps = self.get_physical_qps()
        qp_coors = qps.values[ig]
        u_qp = self.get(state, 'val').reshape(qp_coors.shape)

        # Deformed QP coordinates.
        coors = u_qp + qp_coors

        force = nm.zeros(coors.shape[0], dtype=nm.float64)
        normals = nm.zeros((coors.shape[0], 3), dtype=nm.float64)
        fd = None

        k, f0, eps, a = self._get_force_pars(force_pars, force.shape)

        # Active points in contact change with displacements!
        ii = self.cs.mask_points(coors, nm.abs(eps.min()))

        if diff_var is None:
            if ii.any():
                d, normals[ii] = self.cs.get_distance(coors[ii])
                force[ii] = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 0)

            fmode = 0

        else:
            if ii.any():
                d, normals[ii] = self.cs.get_distance(coors[ii])
                # Force derivative.
                force[ii] = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 1)

                # Force / (R - d).
                aux = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 0)
                fd = nm.zeros_like(force)
                fd[ii] = aux / (self.cs.radius - d)
                fd.shape = qps.shape[ig][:2] + (1, 1)

            fmode = 1

        force.shape = qps.shape[ig][:2] + (1, 1)
        normals.shape = qps.shape[ig][:2] + (3, 1)

        return force, normals, fd, sg, fmode
示例#3
0
def main():
    import os

    import numpy as nm
    import matplotlib.pyplot as plt

    from sfepy.fem import MeshIO
    import sfepy.linalg as la
    from sfepy.mechanics.contact_bodies import ContactSphere, plot_points

    conf_dir = os.path.dirname(__file__)
    io = MeshIO.any_from_filename(filename_mesh, prefix_dir=conf_dir)
    bb = io.read_bounding_box()
    outline = [vv for vv in la.combine(zip(*bb))]

    ax = plot_points(None, nm.array(outline), 'r*')
    csc = materials['cs'][0]
    cs = ContactSphere(csc['.c'], csc['.r'])

    pps = (bb[1] - bb[0]) * nm.random.rand(5000, 3) + bb[0]
    mask = cs.mask_points(pps, 0.0)

    ax = plot_points(ax, cs.centre[None, :], 'b*', ms=30)
    ax = plot_points(ax, pps[mask], 'kv')
    ax = plot_points(ax, pps[~mask], 'r.')

    plt.show()
示例#4
0
    def get_fargs(self, force_pars, centre, radius, virtual, state,
                  mode=None, term_mode=None, diff_var=None, **kwargs):
        sg, _ = self.get_mapping(virtual)

        assert_((force_pars >= 0.0).all(),
                'force parameters must be non-negative!')

        if self.cs is None:
            self.cs = ContactSphere(centre, radius)

        ig = self.char_fun.ig
        qps = self.get_physical_qps()
        qp_coors = qps.values[ig]
        u_qp = self.get(state, 'val').reshape(qp_coors.shape)

        # Deformed QP coordinates.
        coors = u_qp + qp_coors

        force = nm.zeros(coors.shape[0], dtype=nm.float64)
        normals = nm.zeros((coors.shape[0], 3), dtype=nm.float64)
        fd = None

        k, f0, eps, a = self._get_force_pars(force_pars, force.shape)

        # Active points in contact change with displacements!
        ii = self.cs.mask_points(coors, nm.abs(eps.min()))

        if diff_var is None:
            if ii.any():
                d, normals[ii] = self.cs.get_distance(coors[ii])
                force[ii] = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 0)

            fmode = 0

        else:
            if ii.any():
                d, normals[ii] = self.cs.get_distance(coors[ii])
                # Force derivative.
                force[ii] = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 1)

                # Force / (R - d).
                aux = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 0)
                fd = nm.zeros_like(force)
                fd[ii] = aux / (self.cs.radius - d)
                fd.shape = qps.shape[ig][:2] + (1, 1)

            fmode = 1

        force.shape = qps.shape[ig][:2] + (1, 1)
        normals.shape = qps.shape[ig][:2] + (3, 1)

        return force, normals, fd, sg, fmode
示例#5
0
class ContactSphereTerm(ContactPlaneTerm):
    r"""
    Small deformation elastic contact sphere term with penetration penalty.

    The sphere is given by a centre point :math:`\ul{C}` and a radius
    :math:`R`. The contact occurs in points that are closer to :math:`\ul{C}`
    than :math:`R`. In such points, a penetration distance :math:`d(\ul{u}) =
    R - ||\ul{X} + \ul{u} - \ul{C}||` is computed, and a force
    :math:`f(d(\ul{u})) \ul{n}(\ul{u})` is applied, where :math:`\ul{n}(\ul{u})
    = (\ul{X} + \ul{u} - \ul{C}) / ||\ul{X} + \ul{u} - \ul{C}||`. The force
    depends on the non-negative parameters :math:`k` (stiffness) and
    :math:`f_0` (force at zero penetration):

    - If :math:`f_0 = 0`:

      .. math::

         f(d) = 0 \mbox{ for } d \leq 0 \;, \\
         f(d) = k d \mbox{ for } d > 0 \;.

    - If :math:`f_0 > 0`:

      .. math::

         f(d) = 0 \mbox{ for } d \leq -\frac{2 r_0}{k} \;, \\
         f(d) = \frac{k^2}{4 r_0} d^2 + k d + r_0
         \mbox{ for } -\frac{2 r_0}{k} < d \leq 0 \;, \\
         f(d) = k d + f_0 \mbox{ for } d > 0 \;.

      In this case the dependence :math:`f(d)` is smooth, and a (small) force
      is applied even for (small) negative penetrations: :math:`-\frac{2
      r_0}{k} < d \leq 0`.

    :Definition:

    .. math::
        \int_{\Gamma} \ul{v} \cdot f(d(\ul{u})) \ul{n}(\ul{u})

    :Arguments:
        - material_f : :math:`[k, f_0]`
        - material_c : :math:`\ul{C}` (special)
        - material_r : :math:`R` (special)
        - virtual    : :math:`\ul{v}`
        - state      : :math:`\ul{u}`
    """
    name = 'dw_contact_sphere'
    arg_types = ('material_f', 'material_c', 'material_r', 'virtual', 'state')
    arg_shapes = {'material_f' : '1, 2', 'material_c' : '.: D',
                  'material_r' : '.: 1',
                  'virtual' : ('D', 'state'), 'state' : 'D'}
    geometries = ['3_4', '3_8']
    integration = 'surface'

    def __init__(self, *args, **kwargs):
        Term.__init__(self, *args, **kwargs)

        self.cs = None

    @staticmethod
    def function(out, force, normals, fd, geo, fmode):
        bf = geo.bf[0]
        nbf = bf * normals
        nbf.shape = (normals.shape[0], normals.shape[1],
                     bf.shape[2] * normals.shape[2])

        if fmode == 0:
            out_qp = force * nbf[..., None]

        else:
            nbf2 = nbf[..., None] * nbf[..., None, :]

            dim = normals.shape[2]
            n_ep = bf.shape[2]
            bb = bf[:, 0]
            vb = nm.zeros((bf.shape[0], dim, dim * n_ep))
            for ii in range(dim):
                vb[:, ii, ii*n_ep:(ii+1)*n_ep] = bb
            ee = nm.eye(3)[None, ...]
            eebf2 = dot_sequences(vb, dot_sequences(ee, vb), 'ATB')

            out_qp = force * nbf2
            if fd is not None:
                out_qp -= fd * (eebf2[None, :, :, :] - nbf2)

        status = geo.integrate(out, nm.ascontiguousarray(out_qp))

        return status

    def get_fargs(self, force_pars, centre, radius, virtual, state,
                  mode=None, term_mode=None, diff_var=None, **kwargs):
        sg, _ = self.get_mapping(virtual)

        assert_((force_pars >= 0.0).all(),
                'force parameters must be non-negative!')

        if self.cs is None:
            self.cs = ContactSphere(centre, radius)

        ig = self.char_fun.ig
        qps = self.get_physical_qps()
        qp_coors = qps.values[ig]
        u_qp = self.get(state, 'val').reshape(qp_coors.shape)

        # Deformed QP coordinates.
        coors = u_qp + qp_coors

        force = nm.zeros(coors.shape[0], dtype=nm.float64)
        normals = nm.zeros((coors.shape[0], 3), dtype=nm.float64)
        fd = None

        k, f0, eps, a = self._get_force_pars(force_pars, force.shape)

        # Active points in contact change with displacements!
        ii = self.cs.mask_points(coors, nm.abs(eps.min()))

        if diff_var is None:
            if ii.any():
                d, normals[ii] = self.cs.get_distance(coors[ii])
                force[ii] = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 0)

            fmode = 0

        else:
            if ii.any():
                d, normals[ii] = self.cs.get_distance(coors[ii])
                # Force derivative.
                force[ii] = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 1)

                # Force / (R - d).
                aux = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 0)
                fd = nm.zeros_like(force)
                fd[ii] = aux / (self.cs.radius - d)
                fd.shape = qps.shape[ig][:2] + (1, 1)

            fmode = 1

        force.shape = qps.shape[ig][:2] + (1, 1)
        normals.shape = qps.shape[ig][:2] + (3, 1)

        return force, normals, fd, sg, fmode
示例#6
0
class ContactSphereTerm(ContactPlaneTerm):
    r"""
    Small deformation elastic contact sphere term with penetration penalty.

    The sphere is given by a centre point :math:`\ul{C}` and a radius
    :math:`R`. The contact occurs in points that are closer to :math:`\ul{C}`
    than :math:`R`. In such points, a penetration distance :math:`d(\ul{u}) =
    R - ||\ul{X} + \ul{u} - \ul{C}||` is computed, and a force
    :math:`f(d(\ul{u})) \ul{n}(\ul{u})` is applied, where :math:`\ul{n}(\ul{u})
    = (\ul{X} + \ul{u} - \ul{C}) / ||\ul{X} + \ul{u} - \ul{C}||`. The force
    depends on the non-negative parameters :math:`k` (stiffness) and
    :math:`f_0` (force at zero penetration):

    - If :math:`f_0 = 0`:

      .. math::

         f(d) = 0 \mbox{ for } d \leq 0 \;, \\
         f(d) = k d \mbox{ for } d > 0 \;.

    - If :math:`f_0 > 0`:

      .. math::

         f(d) = 0 \mbox{ for } d \leq -\frac{2 r_0}{k} \;, \\
         f(d) = \frac{k^2}{4 r_0} d^2 + k d + r_0
         \mbox{ for } -\frac{2 r_0}{k} < d \leq 0 \;, \\
         f(d) = k d + f_0 \mbox{ for } d > 0 \;.

      In this case the dependence :math:`f(d)` is smooth, and a (small) force
      is applied even for (small) negative penetrations: :math:`-\frac{2
      r_0}{k} < d \leq 0`.

    :Definition:

    .. math::
        \int_{\Gamma} \ul{v} \cdot f(d(\ul{u})) \ul{n}(\ul{u})

    :Arguments:
        - material_f : :math:`[k, f_0]`
        - material_c : :math:`\ul{C}` (special)
        - material_r : :math:`R` (special)
        - virtual    : :math:`\ul{v}`
        - state      : :math:`\ul{u}`
    """
    name = 'dw_contact_sphere'
    arg_types = ('material_f', 'material_c', 'material_r', 'virtual', 'state')
    arg_shapes = {
        'material_f': '1, 2',
        'material_c': '.: D',
        'material_r': '.: 1',
        'virtual': ('D', 'state'),
        'state': 'D'
    }
    geometries = ['3_4', '3_8']
    integration = 'surface'

    def __init__(self, *args, **kwargs):
        Term.__init__(self, *args, **kwargs)

        self.cs = None

    @staticmethod
    def function(out, force, normals, fd, geo, fmode):
        bf = geo.bf[0]
        nbf = bf * normals
        nbf.shape = (normals.shape[0], normals.shape[1],
                     bf.shape[2] * normals.shape[2])

        if fmode == 0:
            out_qp = force * nbf[..., None]

        else:
            nbf2 = nbf[..., None] * nbf[..., None, :]

            dim = normals.shape[2]
            n_ep = bf.shape[2]
            bb = bf[:, 0]
            vb = nm.zeros((bf.shape[0], dim, dim * n_ep))
            for ii in range(dim):
                vb[:, ii, ii * n_ep:(ii + 1) * n_ep] = bb
            ee = nm.eye(3)[None, ...]
            eebf2 = dot_sequences(vb, dot_sequences(ee, vb), 'ATB')

            out_qp = force * nbf2
            if fd is not None:
                out_qp -= fd * (eebf2[None, :, :, :] - nbf2)

        status = geo.integrate(out, nm.ascontiguousarray(out_qp))

        return status

    def get_fargs(self,
                  force_pars,
                  centre,
                  radius,
                  virtual,
                  state,
                  mode=None,
                  term_mode=None,
                  diff_var=None,
                  **kwargs):
        sg, _ = self.get_mapping(virtual)

        assert_((force_pars >= 0.0).all(),
                'force parameters must be non-negative!')

        if self.cs is None:
            self.cs = ContactSphere(centre, radius)

        ig = self.char_fun.ig
        qps = self.get_physical_qps()
        qp_coors = qps.values[ig]
        u_qp = self.get(state, 'val').reshape(qp_coors.shape)

        # Deformed QP coordinates.
        coors = u_qp + qp_coors

        force = nm.zeros(coors.shape[0], dtype=nm.float64)
        normals = nm.zeros((coors.shape[0], 3), dtype=nm.float64)
        fd = None

        k, f0, eps, a = self._get_force_pars(force_pars, force.shape)

        # Active points in contact change with displacements!
        ii = self.cs.mask_points(coors, nm.abs(eps.min()))

        if diff_var is None:
            if ii.any():
                d, normals[ii] = self.cs.get_distance(coors[ii])
                force[ii] = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 0)

            fmode = 0

        else:
            if ii.any():
                d, normals[ii] = self.cs.get_distance(coors[ii])
                # Force derivative.
                force[ii] = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 1)

                # Force / (R - d).
                aux = self.smooth_f(d, k[ii], f0[ii], a[ii], eps[ii], 0)
                fd = nm.zeros_like(force)
                fd[ii] = aux / (self.cs.radius - d)
                fd.shape = qps.shape[ig][:2] + (1, 1)

            fmode = 1

        force.shape = qps.shape[ig][:2] + (1, 1)
        normals.shape = qps.shape[ig][:2] + (3, 1)

        return force, normals, fd, sg, fmode