"""
Flexoelectricity related terms.
"""
import numpy as nm
from sfepy.mechanics.tensors import dim2sym
from sfepy.terms.terms_multilinear import ETermBase
[docs]
def make_grad2strain(dim):
if dim == 3:
g2s = nm.array([
[1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 1, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 1, 0],
], dtype=nm.float64)
g2s = g2s.reshape((1, 1, 6, 9))
elif dim == 2:
g2s = nm.array([
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 1, 1, 0],
], dtype=nm.float64)
g2s = g2s.reshape((1, 1, 3, 4))
elif dim == 1:
g2s = nm.array([
[1],
], dtype=nm.float64)
g2s = g2s.reshape((1, 1, 1, 1))
else:
raise ValueError(f'space dimension must be 1, 2, or 3! (is {dim})')
return g2s
[docs]
class MixedStrainGradElasticTerm(ETermBase):
r"""
Flexoelectric strain gradient elasticity term, mixed formulation.
Additional evaluation modes:
- `'strain'` - compute strain from the displacement gradient (state)
variable.
:Definition:
.. math::
\int_{\Omega} a_{ijklmn}\ e_{ij,k}(\ull{\delta w}) \ e_{lm,n}(\ull{w})
:Arguments:
- material: :math:`a_{ijklmn}`
- virtual/parameter_1: :math:`\ull{\delta w}`
- state/parameter_2: :math:`\ull{w}`
"""
name = 'de_m_sg_elastic'
arg_types = (('material', 'virtual', 'state'),
('material', 'parameter_1', 'parameter_2'))
arg_shapes = {'material' : 'SD, SD', 'virtual' : ('D2', 'state'),
'state' : 'D2', 'parameter_1' : 'D2', 'parameter_2' : 'D2'}
modes = ('weak', 'eval')
[docs]
def get_function(self, mat, virtual, state, mode=None, term_mode=None,
diff_var=None, **kwargs):
dim = self.region.dim
sym = dim2sym(dim)
aux = make_grad2strain(dim)
n_qp = mat.shape[1]
mat = mat.reshape((-1, n_qp, dim, sym, dim, sym))
if term_mode is None:
return self.make_function(
'kIlJ,Ii,Jj,i.k,j.l',
(mat, 'mat'), (aux, 'aux1'), (aux, 'aux2'), virtual, state,
mode=mode, diff_var=diff_var,
)
elif term_mode == 'strain':
return self.make_function(
'Ii,i', (aux, 'aux1'), state, mode=mode, diff_var=None,
)
elif term_mode == 'grad_strain':
return self.make_function(
'Jj,j.l', (aux, 'aux2'), state, mode=mode, diff_var=None,
)
elif term_mode == 'double_stress':
return self.make_function(
'kIlJ,Ii,Jj,j.l',
(mat, 'mat'), (aux, 'aux1'), (aux, 'aux2'), state,
mode=mode, diff_var=None,
)
else:
raise ValueError('unsupported term mode in %s! (%s)'
% (self.name, term_mode))
[docs]
class MixedFlexoCouplingTerm(ETermBase):
r"""
Flexoelectric coupling term, mixed formulation.
:Definition:
.. math::
\int_{\Omega} f_{ijkl}\ e_{jk,l}(\ull{\delta w}) \nabla_i p \\
\int_{\Omega} f_{ijkl}\ e_{jk,l}(\ull{w}) \nabla_i q
:Arguments 1:
- material: :math:`f_{ijkl}`
- virtual/parameter_t: :math:`\ull{\delta w}`
- state/parameter_s: :math:`p`
:Arguments 2:
- material: :math:`f_{ijkl}`
- state : :math:`\ull{w}`
- virtual : :math:`q`
"""
name = 'de_m_flexo_coupling'
arg_types = (('material', 'virtual', 'state'),
('material', 'state', 'virtual'),
('material', 'parameter_t', 'parameter_s'))
arg_shapes = [{'material' : 'D, SD',
'virtual/dw-p' : ('D2', None), 'state/dw-p' : 1,
'virtual/dp-w' : (1, None), 'state/dp-w' : 'D2',
'parameter_t' : 'D2', 'parameter_s' : 1}]
modes = ('dw-p', 'dp-w', 'eval')
[docs]
def get_function(self, mat, tvar, svar, mode=None, term_mode=None,
diff_var=None, **kwargs):
dim = self.region.dim
sym = dim2sym(dim)
aux = make_grad2strain(dim)
n_qp = mat.shape[1]
mat = mat.reshape((-1, n_qp, dim, dim, sym))
if term_mode is None:
fun = self.make_function(
'jkI,Ii,i.k,0.j',
(mat, 'mat'), (aux, 'aux'), tvar, svar,
mode=mode, diff_var=diff_var,
)
elif term_mode == 'electric_displacement':
fun = self.make_function(
'jkI,Ii,i.k',
(mat, 'mat'), (aux, 'aux'), tvar,
mode=mode, diff_var=diff_var,
)
elif term_mode == 'double_stress':
fun = self.make_function(
'jkI,Ii,0.j',
(mat, 'mat'), (aux, 'aux'), svar,
mode=mode, diff_var=diff_var,
)
else:
raise ValueError('unsupported term mode in %s! (%s)'
% (self.name, term_mode))
return fun
[docs]
class MixedFlexoTerm(ETermBase):
r"""
Mixed formulation displacement gradient consistency term.
:Definition:
.. math::
\int_{\Omega} v_{i,j} a_{ij} \\
\int_{\Omega} u_{i,j} \delta a_{ij}
:Arguments 1:
- virtual/parameter_v: :math:`\ul{v}`
- state/parameter_t: :math:`\ull{a}`
:Arguments 2:
- state : :math:`\ul{u}`
- virtual : :math:`\ull{\delta a}`
"""
name = 'de_m_flexo'
arg_types = (('virtual', 'state'),
('state', 'virtual'),
('parameter_v', 'parameter_t'))
arg_shapes = [{'virtual/du-a' : ('D', None), 'state/du-a' : 'D2',
'virtual/da-u' : ('D2', None), 'state/da-u' : 'D',
'parameter_v' : 'D', 'parameter_t' : 'D2'},
{'opt_material' : None}]
modes = ('du-a', 'da-u', 'eval')
[docs]
def get_function(self, vvar, tvar, mode=None, term_mode=None,
diff_var=None, **kwargs):
fun = self.make_function(
'v(i.j)->I,I', vvar, tvar, mode=mode, diff_var=diff_var,
)
return fun