from __future__ import absolute_import
import numpy as nm
from sfepy.terms.terms import Term
from sfepy.linalg import dot_sequences
[docs]
class NonPenetrationTerm(Term):
r"""
Non-penetration condition in the weak sense.
:Definition:
.. math::
\int_{\Gamma} c \lambda \ul{n} \cdot \ul{v} \mbox{ , }
\int_{\Gamma} c \hat\lambda \ul{n} \cdot \ul{u} \\
\int_{\Gamma} \lambda \ul{n} \cdot \ul{v} \mbox{ , }
\int_{\Gamma} \hat\lambda \ul{n} \cdot \ul{u}
:Arguments 1:
- material : :math:`c` (optional)
- virtual : :math:`\ul{v}`
- state : :math:`\lambda`
:Arguments 2:
- material : :math:`c` (optional)
- state : :math:`\ul{u}`
- virtual : :math:`\hat\lambda`
"""
name = 'dw_non_penetration'
arg_types = (('opt_material', 'virtual', 'state'),
('opt_material', 'state', 'virtual'))
arg_shapes = [{'opt_material' : '1, 1',
'virtual/grad' : ('D', None), 'state/grad' : 1,
'virtual/div' : (1, None), 'state/div' : 'D'},
{'opt_material' : None}]
modes = ('grad', 'div')
integration = 'facet'
[docs]
@staticmethod
def function(out, val_qp, ebf, bf, mat, sg, diff_var, mode):
"""
`ebf` belongs to vector variable, `bf` to scalar variable.
"""
normals = sg.normal
n_fa = out.shape[0]
if diff_var is None:
if mode == 'grad':
ebf_t = nm.tile(ebf.transpose((0, 1, 3, 2)), (n_fa, 1, 1, 1))
nl = normals * val_qp
eftnl = mat * dot_sequences(ebf_t, nl)
status = sg.integrate(out, eftnl, 0)
else:
bf_t = nm.tile(bf.transpose((0, 1, 3, 2)), (n_fa, 1, 1, 1))
ntu = (normals * val_qp).sum(axis=-2)[...,None]
ftntu = mat * (bf_t * ntu)
status = sg.integrate(out, ftntu, 0)
else:
ebf_t = nm.tile(ebf.transpose((0, 1, 3, 2)), (n_fa, 1, 1, 1))
bf_ = nm.tile(bf, (n_fa, 1, 1, 1))
eftn = mat * dot_sequences(ebf_t, normals)
eftnf = eftn * bf_
if mode == 'grad':
status = sg.integrate(out, eftnf, 0)
else:
ftntef = nm.ascontiguousarray(eftnf.transpose((0, 1, 3, 2)))
status = sg.integrate(out, ftntef, 0)
return status
[docs]
def get_fargs(self, mat, vvar, svar,
mode=None, term_mode=None, diff_var=None, **kwargs):
from sfepy.discrete.variables import expand_basis
if self.mode == 'grad':
qp_var = svar
else:
qp_var = vvar
val_qp = self.get(qp_var, 'val')
vsg, _ = self.get_mapping(vvar)
ssg, _ = self.get_mapping(svar)
n_fa, n_qp, dim, n_fn, n_c = self.get_data_shape(vvar)
if mat is None:
mat = nm.ones((1, n_qp, 1, 1), dtype=nm.float64)
ebf = expand_basis(vsg.bf, dim)
return val_qp, ebf, ssg.bf, mat, vsg, diff_var, self.mode
[docs]
class NonPenetrationPenaltyTerm(Term):
r"""
Non-penetration condition in the weak sense using a penalty.
:Definition:
.. math::
\int_{\Gamma} c (\ul{n} \cdot \ul{v}) (\ul{n} \cdot \ul{u})
:Arguments:
- material : :math:`c`
- virtual : :math:`\ul{v}`
- state : :math:`\ul{u}`
"""
name = 'dw_non_penetration_p'
arg_types = ('material', 'virtual', 'state')
arg_shapes = {'material' : '1, 1',
'virtual' : ('D', 'state'), 'state' : 'D'}
integration = 'facet'
[docs]
@staticmethod
def function(out, val_qp, ebf, mat, sg, diff_var):
normals = sg.normal
n_fa = out.shape[0]
ebf_t = nm.tile(ebf.transpose((0, 1, 3, 2)), (n_fa, 1, 1, 1))
if diff_var is None:
nu = dot_sequences(normals, val_qp, 'ATB')
nt = dot_sequences(ebf_t, normals)
entnu = mat * nt * nu
status = sg.integrate(out, entnu, 0)
else:
nt = dot_sequences(ebf_t, normals)
entn = mat * dot_sequences(nt, nt, 'ABT')
status = sg.integrate(out, entn, 0)
return status
[docs]
def get_fargs(self, mat, vvar, svar,
mode=None, term_mode=None, diff_var=None, **kwargs):
from sfepy.discrete.variables import expand_basis
if diff_var is None:
val_qp = self.get(svar, 'val')
else:
val_qp = nm.array([0], ndmin=4, dtype=nm.float64)
sg, _ = self.get_mapping(vvar)
n_fa, n_qp, dim, n_fn, n_c = self.get_data_shape(vvar)
ebf = expand_basis(sg.bf, dim)
return val_qp, ebf, mat, sg, diff_var