import numpy as nm

from sfepy.linalg import dot_sequences
from sfepy.terms.terms import Term, terms

class DivGradTerm(Term):
    r"""
    Diffusion term.

    :Definition:

    .. math::
        \int_{\Omega} \nu\ \nabla \ul{v} : \nabla \ul{u} \mbox{ , }
        \int_{\Omega} \nu\ \nabla \ul{u} : \nabla \ul{w} \\
        \int_{\Omega} \nabla \ul{v} : \nabla \ul{u} \mbox{ , }
        \int_{\Omega} \nabla \ul{u} : \nabla \ul{w}

    :Arguments 1:
        - material : :math:`\nu` (viscosity, optional)
        - virtual  : :math:`\ul{v}`
        - state    : :math:`\ul{u}`

    :Arguments 2:
        - material    : :math:`\nu` (viscosity, optional)
        - parameter_1 : :math:`\ul{u}`
        - parameter_2 : :math:`\ul{w}`
    """
    name = 'dw_div_grad'
    arg_types = (('opt_material', 'virtual', 'state'),
                 ('opt_material', 'parameter_1', 'parameter_2'))
    arg_shapes = {'opt_material' : '1, 1', 'virtual' : ('D', 'state'),
                  'state' : 'D', 'parameter_1' : 'D', 'parameter_2' : 'D'}
    modes = ('weak', 'eval')

    function = staticmethod(terms.term_ns_asm_div_grad)

    def d_div_grad(self, out, grad1, grad2, mat, vg, fmode):
        sh = grad1.shape
        g1 = grad1.reshape((sh[0], sh[1], sh[2] * sh[3]))
        g2 = grad2.reshape((sh[0], sh[1], sh[2] * sh[3]))
        aux = mat * 
dot_sequences(g1[..., None], g2, 'ATB')