예제 #1
0
    def matrix(self, shape=None):
        """
        This function returns the object as a matrix of DFT or iDFT resp.
        """
        N=self.N
        prodN=np.prod(N)
        if shape is not None:
            dim=np.prod(np.array(shape))
        elif hasattr(self, 'shape'):
            dim=np.prod(np.array(shape))
        else:
            raise ValueError('Missing shape of the DFT.')

        proddN=dim*prodN
        ZN_input=Grid.get_ZNl(N, fft_form=0)
        ZN_output=Grid.get_ZNl(N, fft_form='c')

        if self.inverse:
            DFTcoef=lambda k, l, N: np.exp(2*np.pi*1j*np.sum(k*l/N))
        else:
            DFTcoef=lambda k, l, N: np.exp(-2*np.pi*1j*np.sum(k*l/N))/np.prod(N)

        DTM=np.zeros([self.pN(), self.pN()], dtype=np.complex128)
        for ii, kk in enumerate(itertools.product(*tuple(ZN_output))):
            for jj, ll in enumerate(itertools.product(*tuple(ZN_input))):
                DTM[ii, jj]=DFTcoef(np.array(kk, dtype=np.float),
                                      np.array(ll), N)

        DTMd=npmatlib.zeros([proddN, proddN], dtype=np.complex128)
        for ii in range(dim):
            DTMd[prodN*ii:prodN*(ii+1), prodN*ii:prodN*(ii+1)]=DTM
        return DTMd
예제 #2
0
    def matrix(self, shape=None):
        """
        This function returns the object as a matrix of DFT or iDFT resp.
        """
        N = self.N
        prodN = np.prod(N)
        if shape is not None:
            dim = np.prod(np.array(shape))
        elif hasattr(self, 'shape'):
            dim = np.prod(np.array(shape))
        else:
            raise ValueError('Missing shape of the DFT.')

        proddN = dim * prodN
        ZN_input = Grid.get_ZNl(N, fft_form=0)
        ZN_output = Grid.get_ZNl(N, fft_form='c')

        if self.inverse:
            DFTcoef = lambda k, l, N: np.exp(2 * np.pi * 1j * np.sum(k * l / N)
                                             )
        else:
            DFTcoef = lambda k, l, N: np.exp(-2 * np.pi * 1j * np.sum(
                k * l / N)) / np.prod(N)

        DTM = np.zeros([self.pN(), self.pN()], dtype=np.complex128)
        for ii, kk in enumerate(itertools.product(*tuple(ZN_output))):
            for jj, ll in enumerate(itertools.product(*tuple(ZN_input))):
                DTM[ii, jj] = DFTcoef(np.array(kk, dtype=np.float),
                                      np.array(ll), N)

        DTMd = npmatlib.zeros([proddN, proddN], dtype=np.complex128)
        for ii in range(dim):
            DTMd[prodN * ii:prodN * (ii + 1),
                 prodN * ii:prodN * (ii + 1)] = DTM
        return DTMd
예제 #3
0
def div(X):
    if X.shape == (1, ):
        shape = ()
    else:
        shape = X.shape[:-1]
    assert (X.shape[-1] == X.dim)
    assert (X.order == 1)

    dX = Tensor(shape=shape, N=X.N, Fourier=True, fft_form=X.fft_form)
    if X.Fourier:
        FX = X
    else:
        F = DFT(N=X.N, fft_form=X.fft_form)
        FX = F(X)

    dim = len(X.N)
    freq = Grid.get_freq(X.N, X.Y, fft_form=FX.fft_form)
    strfreq = 'xyz'
    coef = 2 * np.pi * 1j

    for ii in range(X.dim):
        mul_str = '{0},...{1}->...{1}'.format(strfreq[ii], strfreq[:dim])
        dX.val += np.einsum(mul_str,
                            coef * freq[ii],
                            FX.val[ii],
                            dtype=np.complex)

    if not X.Fourier:
        iF = DFT(N=X.N, inverse=True, fft_form=dX.fft_form)
        dX = iF(dX)
    dX.name = 'div({0})'.format(X.name[:10])
    return dX
예제 #4
0
def get_weights_lin(h, Nbar, Y):
    """
    it evaluates integral weights,
    which are used for upper-lower bounds calculation,
    with bilinear inclusion at rectangular area

    Parameters
    ----------
    h - the parameter determining the size of inclusion (half-size of support)
    Nbar - no. of points of regular grid where the weights are evaluated
    Y - the size of periodic unit cell

    Returns
    -------
    Wphi - integral weights at regular grid sizing Nbar
    """
    d = np.size(Y)
    meas_puc = np.prod(Y)
    ZN2l = Grid.get_ZNl(Nbar, fft_form='c')
    Wphi = np.ones(Nbar) / meas_puc
    for ii in np.arange(d):
        Nshape = np.ones(d, dtype=np.int)
        Nshape[ii] = Nbar[ii]
        Nrep = np.copy(Nbar)
        Nrep[ii] = 1
        Wphi *= h[ii] * np.tile(
            np.reshape((np.sinc(h[ii] * ZN2l[ii] / Y[ii]))**2, Nshape), Nrep)
    return Wphi
예제 #5
0
def get_weights_circ(r, Nbar, Y):
    """
    it evaluates integral weights,
    which are used for upper-lower bounds calculation,
    with constant circular inclusion

    Parameters
    ----------
        r - the parameter determining the size of inclusion
        Nbar - no. of points of regular grid where the weights are evaluated
        Y - the size of periodic unit cell
    Returns
    -------
        Wphi - integral weights at regular grid sizing Nbar
    """
    d = np.size(Y)
    ZN2l = Grid.get_ZNl(Nbar, fft_form='c')
    meas_puc = np.prod(Y)
    circ = 0
    for m in range(d):
        Nshape = np.ones(d, dtype=np.int)
        Nshape[m] = Nbar[m]
        Nrep = np.copy(Nbar)
        Nrep[m] = 1
        xi_p2 = np.tile(np.reshape((ZN2l[m] / Y[m])**2, Nshape), Nrep)
        circ += xi_p2
    circ = circ**0.5
    ind = mean_index(Nbar, fft_form='c')
    circ[ind] = 1.

    Wphi = r**2 * sp.jn(1, 2 * np.pi * circ * r) / (circ * r)
    Wphi[ind] = np.pi * r**2
    Wphi = Wphi / meas_puc
    return Wphi
예제 #6
0
def scalar(N, Y, fft_form=fft_form_default):
    dim = np.size(N)
    N = np.array(N, dtype=np.int)

    xi = Grid.get_freq(N, Y, fft_form=fft_form)
    N_fft=tuple(xi[i].size for i in range(dim))
    hGrad = np.zeros((dim,)+N_fft) # zero initialize
    for ind in itertools.product(*[range(n) for n in N_fft]):
        for i in range(dim):
            hGrad[i][ind] = xi[i][ind[i]]

    kok= np.einsum('i...,j...->ij...', hGrad, hGrad).real
    k2 = np.einsum('i...,i...', hGrad, hGrad).real
    ind_center=mean_index(N, fft_form=fft_form)
    k2[ind_center]=1.

    G0lval=np.zeros_like(kok)
    Ival=np.zeros_like(kok)
    for ii in range(dim): # diagonal components
        G0lval[ii, ii][ind_center] = 1
        Ival[ii, ii] = 1
    G1l=Tensor(name='G1', val=kok/k2, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form)
    G0l=Tensor(name='G1', val=G0lval, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form)
    I = Tensor(name='I', val=Ival, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form)
    G2l=I-G1l-G0l
    return G0l, G1l, G2l
예제 #7
0
def scalar(N, Y, fft_form=fft_form_default):
    dim = np.size(N)
    N = np.array(N, dtype=np.int)

    xi = Grid.get_freq(N, Y, fft_form=fft_form)
    N_fft=tuple(xi[i].size for i in range(dim))
    hGrad = np.zeros((dim,)+N_fft) # zero initialize
    for ind in itertools.product(*[list(range(n)) for n in N_fft]):
        for i in range(dim):
            hGrad[i][ind] = xi[i][ind[i]]

    kok= np.einsum('i...,j...->ij...', hGrad, hGrad).real
    k2 = np.einsum('i...,i...', hGrad, hGrad).real
    ind_center=mean_index(N, fft_form=fft_form)
    k2[ind_center]=1.

    G0lval=np.zeros_like(kok)
    Ival=np.zeros_like(kok)
    for ii in range(dim): # diagonal components
        G0lval[ii, ii][ind_center] = 1
        Ival[ii, ii] = 1
    G1l=Tensor(name='G1', val=kok/k2, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form)
    G0l=Tensor(name='G1', val=G0lval, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form)
    I = Tensor(name='I', val=Ival, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form)
    G2l=I-G1l-G0l
    return G0l, G1l, G2l
예제 #8
0
def get_weights_circ(r, Nbar, Y):
    """
    it evaluates integral weights,
    which are used for upper-lower bounds calculation,
    with constant circular inclusion

    Parameters
    ----------
        r - the parameter determining the size of inclusion
        Nbar - no. of points of regular grid where the weights are evaluated
        Y - the size of periodic unit cell
    Returns
    -------
        Wphi - integral weights at regular grid sizing Nbar
    """
    d = np.size(Y)
    ZN2l = Grid.get_ZNl(Nbar, fft_form='c')
    meas_puc = np.prod(Y)
    circ = 0
    for m in range(d):
        Nshape = np.ones(d, dtype=np.int)
        Nshape[m] = Nbar[m]
        Nrep = np.copy(Nbar)
        Nrep[m] = 1
        xi_p2 = np.tile(np.reshape((ZN2l[m]/Y[m])**2, Nshape), Nrep)
        circ += xi_p2
    circ = circ**0.5
    ind = mean_index(Nbar, fft_form='c')
    circ[ind] = 1.

    Wphi = r**2 * sp.jn(1, 2*np.pi*circ*r) / (circ*r)
    Wphi[ind] = np.pi*r**2
    Wphi = Wphi / meas_puc
    return Wphi
예제 #9
0
def grad(X):
    if X.shape==(1,):
        shape=(X.dim,)
    else:
        shape=X.shape+(X.dim,)
    name='grad({0})'.format(X.name[:10])
    gX=Tensor(name=name, shape=shape, N=X.N,
              Fourier=True, fft_form=X.fft_form)
    if X.Fourier:
        FX=X
    else:
        F=DFT(N=X.N, fft_form=X.fft_form) # TODO:change to X.fourier()
        FX=F(X)

    dim=len(X.N)
    freq=Grid.get_freq(X.N, X.Y, fft_form=X.fft_form)
    strfreq='xyz'
    coef=2*np.pi*1j
    val=np.empty((X.dim,)+X.shape+X.N_fft, dtype=np.complex)

    for ii in range(X.dim):
        mul_str='{0},...{1}->...{1}'.format(strfreq[ii], strfreq[:dim])
        val[ii]=np.einsum(mul_str, coef*freq[ii], FX.val, dtype=np.complex)

    if X.shape==(1,):
        gX.val=np.squeeze(val)
    else:
        gX.val=np.moveaxis(val, 0, X.order)

    if not X.Fourier:
        iF=DFT(N=X.N, inverse=True, fft_form=gX.fft_form)
        gX=iF(gX)
    gX.name='grad({0})'.format(X.name[:10])
    return gX
예제 #10
0
def grad(X):
    if X.shape==(1,):
        shape=(X.dim,)
    else:
        shape=X.shape+(X.dim,)
    name='grad({0})'.format(X.name[:10])
    gX=Tensor(name=name, shape=shape, N=X.N,
              Fourier=True, fft_form=X.fft_form)
    if X.Fourier:
        FX=X
    else:
        F=DFT(N=X.N, fft_form=X.fft_form) # TODO:change to X.fourier()
        FX=F(X)

    dim=len(X.N)
    freq=Grid.get_freq(X.N, X.Y, fft_form=X.fft_form)
    strfreq='xyz'
    coef=2*np.pi*1j
    val=np.empty((X.dim,)+X.shape+X.N_fft, dtype=np.complex)

    for ii in range(X.dim):
        mul_str='{0},...{1}->...{1}'.format(strfreq[ii], strfreq[:dim])
        val[ii]=np.einsum(mul_str, coef*freq[ii], FX.val, dtype=np.complex)

    if X.shape==(1,):
        gX.val=np.squeeze(val)
    else:
        gX.val=np.moveaxis(val, 0, X.order)

    if not X.Fourier:
        iF=DFT(N=X.N, inverse=True, fft_form=gX.fft_form)
        gX=iF(gX)
    gX.name='grad({0})'.format(X.name[:10])
    return gX
예제 #11
0
def div(X):
    if X.shape==(1,):
        shape=()
    else:
        shape=X.shape[:-1]
    assert(X.shape[-1]==X.dim)
    assert(X.order==1)

    dX=Tensor(shape=shape, N=X.N, Fourier=True, fft_form=X.fft_form)
    if X.Fourier:
        FX=X
    else:
        F=DFT(N=X.N, fft_form=X.fft_form)
        FX=F(X)

    dim=len(X.N)
    freq=Grid.get_freq(X.N, X.Y, fft_form=FX.fft_form)
    strfreq='xyz'
    coef=2*np.pi*1j

    for ii in range(X.dim):
        mul_str='{0},...{1}->...{1}'.format(strfreq[ii], strfreq[:dim])
        dX.val+=np.einsum(mul_str, coef*freq[ii], FX.val[ii], dtype=np.complex)

    if not X.Fourier:
        iF=DFT(N=X.N, inverse=True, fft_form=dX.fft_form)
        dX=iF(dX)
    dX.name='div({0})'.format(X.name[:10])
    return dX
예제 #12
0
def get_weights_lin(h, Nbar, Y):
    """
    it evaluates integral weights,
    which are used for upper-lower bounds calculation,
    with bilinear inclusion at rectangular area

    Parameters
    ----------
    h - the parameter determining the size of inclusion (half-size of support)
    Nbar - no. of points of regular grid where the weights are evaluated
    Y - the size of periodic unit cell

    Returns
    -------
    Wphi - integral weights at regular grid sizing Nbar
    """
    d = np.size(Y)
    meas_puc = np.prod(Y)
    ZN2l = Grid.get_ZNl(Nbar, fft_form='c')
    Wphi = np.ones(Nbar) / meas_puc
    for ii in np.arange(d):
        Nshape = np.ones(d, dtype=np.int)
        Nshape[ii] = Nbar[ii]
        Nrep = np.copy(Nbar)
        Nrep[ii] = 1
        Wphi *= h[ii]*np.tile(np.reshape((np.sinc(h[ii]*ZN2l[ii]/Y[ii]))**2,
                                         Nshape), Nrep)
    return Wphi
예제 #13
0
 def get_A_GaNi(self, N, primaldual='primal', tensor=True):
     """
     Returns stiffness matrix for a scheme with trapezoidal quadrature rule.
     """
     coord = Grid.get_coordinates(N, self.Y)
     A = self.evaluate(coord, tensor=tensor)
     if primaldual is 'dual':
         A = A.inv()
     return A.shift()
예제 #14
0
 def get_A_GaNi(self, N, primaldual='primal', tensor=True):
     """
     Returns stiffness matrix for a scheme with trapezoidal quadrature rule.
     """
     coord = Grid.get_coordinates(N, self.Y)
     A = self.evaluate(coord, tensor=tensor)
     if primaldual is 'dual':
         A = A.inv()
     return A.shift()
예제 #15
0
def potential(X, small_strain=False):
    if X.Fourier:
        FX = X
    else:
        F = DFT(N=X.N, fft_form=X.fft_form)
        FX = F(X)

    freq = Grid.get_freq(X.N, X.Y, fft_form=FX.fft_form)
    if X.order == 1:
        assert (X.dim == X.shape[0])
        iX = Tensor(name='potential({0})'.format(X.name[:10]),
                    shape=(1, ),
                    N=X.N,
                    Fourier=True,
                    fft_form=FX.fft_form)
        iX.val[0] = potential_scalar(FX.val,
                                     freq=freq,
                                     mean_index=FX.mean_index())

    elif X.order == 2:
        assert (X.dim == X.shape[0])
        assert (X.dim == X.shape[1])
        iX = Tensor(name='potential({0})'.format(X.name[:10]),
                    shape=(X.dim, ),
                    N=X.N,
                    Fourier=True,
                    fft_form=FX.fft_form)
        if not small_strain:
            for ii in range(X.dim):
                iX.val[ii] = potential_scalar(FX.val[ii],
                                              freq=freq,
                                              mean_index=FX.mean_index())

        else:
            assert ((X - X.transpose()).norm() < 1e-14)  # symmetricity
            omeg = FX.zeros_like()  # non-symmetric part of the gradient
            gomeg = Tensor(name='potential({0})'.format(X.name[:10]),
                           shape=FX.shape + (X.dim, ),
                           N=X.N,
                           Fourier=True)
            grad_ep = grad(FX)  # gradient of strain
            gomeg.val = np.einsum('ikj...->ijk...', grad_ep.val) - np.einsum(
                'jki...->ijk...', grad_ep.val)
            for ij in itertools.product(list(range(X.dim)), repeat=2):
                omeg.val[ij] = potential_scalar(gomeg.val[ij],
                                                freq=freq,
                                                mean_index=FX.mean_index())

            gradu = FX + omeg
            iX = potential(gradu, small_strain=False)

    if X.Fourier:
        return iX
    else:
        iF = DFT(N=X.N, inverse=True, fft_form=FX.fft_form)
        return iF(iX)
예제 #16
0
 def savefig(self, fname='material.pdf', N=50 * np.ones(2)):
     import pylab as pl
     pl.figure(num=None, figsize=(3, 3), dpi=1000)
     coord = Grid.get_coordinates(N, self.Y)
     vals = self.evaluate(coord)[0, 0]
     pl.pcolor(coord[0], coord[1], -vals)
     pl.xlim([-self.Y[0] / 2, self.Y[0] / 2])
     pl.ylim([-self.Y[1] / 2, self.Y[1] / 2])
     pl.xlabel(r'coordinate $x_1$')
     pl.ylabel(r'coordinate $x_2$')
     pl.savefig(fname, pad_inches=0.02, bbox_inches='tight')
     pl.close()
예제 #17
0
 def savefig(self, fname='material.pdf', N=50*np.ones(2)):
     import pylab as pl
     pl.figure(num=None, figsize=(3,3), dpi=1000)
     coord = Grid.get_coordinates(N, self.Y)
     vals = self.evaluate(coord)[0, 0]
     pl.pcolor(coord[0], coord[1], -vals)
     pl.xlim([-self.Y[0]/2, self.Y[0]/2])
     pl.ylim([-self.Y[1]/2, self.Y[1]/2])
     pl.xlabel(r'coordinate $x_1$')
     pl.ylabel(r'coordinate $x_2$')
     pl.savefig(fname, pad_inches=0.02, bbox_inches='tight')
     pl.close()
예제 #18
0
def get_shift_inclusion(N, h, Y):
    N = np.array(N, dtype=np.int)
    Y = np.array(Y, dtype=np.float)
    dim = N.size
    ZN = Grid.get_ZNl(N)
    SS = np.ones(N, dtype=np.complex128)
    for ii in np.arange(dim):
        Nshape = np.ones(dim, dtype=np.int)
        Nshape[ii] = N[ii]
        Nrep = N
        Nrep[ii] = 1
        SS *= np.tile(np.reshape(np.exp(-2*np.pi*1j*(h[ii]*ZN[ii]/Y[ii])),
                                 Nshape), Nrep)
    return SS
예제 #19
0
def get_shift_inclusion(N, h, Y):
    N = np.array(N, dtype=np.int)
    Y = np.array(Y, dtype=np.float)
    dim = N.size
    ZN = Grid.get_ZNl(N)
    SS = np.ones(N, dtype=np.complex128)
    for ii in np.arange(dim):
        Nshape = np.ones(dim, dtype=np.int)
        Nshape[ii] = N[ii]
        Nrep = N
        Nrep[ii] = 1
        SS *= np.tile(
            np.reshape(np.exp(-2 * np.pi * 1j * (h[ii] * ZN[ii] / Y[ii])),
                       Nshape), Nrep)
    return SS
예제 #20
0
def grad_tensor(N, Y=None, fft_form=fft_form_default):
    if Y is None:
        Y = np.ones_like(N)
    # scalar valued versions of gradient and divergence
    N = np.array(N, dtype=np.int)
    dim = N.size

    freq = Grid.get_xil(N, Y, fft_form=fft_form)
    N_fft=tuple(freq[i].size for i in range(dim))
    hGrad = np.zeros((dim,)+ N_fft) # zero initialize
    for ind in itertools.product(*[range(n) for n in N_fft]):
        for i in range(dim):
            hGrad[i][ind] = freq[i][ind[i]]
    hGrad = hGrad*2*np.pi*1j
    return Tensor(name='hgrad', val=hGrad, order=1, N=N, multype='grad',
                  Fourier=True, fft_form=fft_form)
예제 #21
0
def grad_tensor(N, Y=None, fft_form=fft_form_default):
    if Y is None:
        Y = np.ones_like(N)
    # scalar valued versions of gradient and divergence
    N = np.array(N, dtype=np.int)
    dim = N.size

    freq = Grid.get_xil(N, Y, fft_form=fft_form)
    N_fft=tuple(freq[i].size for i in range(dim))
    hGrad = np.zeros((dim,)+ N_fft) # zero initialize
    for ind in itertools.product(*[list(range(n)) for n in N_fft]):
        for i in range(dim):
            hGrad[i][ind] = freq[i][ind[i]]
    hGrad = hGrad*2*np.pi*1j
    return Tensor(name='hgrad', val=hGrad, order=1, N=N, multype='grad',
                  Fourier=True, fft_form=fft_form)
예제 #22
0
def curl_norm(e, Y):
    """
    it calculates curl-based norm,
    it controls that the fields are curl-free with zero mean as
    it is required of electric fields

    Parameters
    ----------
        e - electric field
        Y - the size of periodic unit cell

    Returns
    -------
        curlnorm - curl-based norm
    """
    N=np.array(np.shape(e[0]))
    d=np.size(N)
    xil=Grid.get_xil(N, Y)
    xiM=[]
    Fe=[]
    for m in np.arange(d):
        Nshape=np.ones(d)
        Nshape[m]=N[m]
        Nrep=np.copy(N)
        Nrep[m]=1
        xiM.append(np.tile(np.reshape(xil[m], Nshape), Nrep))
        Fe.append(DFT.fftnc(e[m], N)/np.prod(N))

    if d==2:
        Fe.append(np.zeros(N))
        xiM.append(np.zeros(N))

    ind_mean=tuple(np.fix(N/2))
    curl=[]
    e0=[]
    for m in np.arange(3):
        j=(m+1)%3
        k=(j+1)%3
        curl.append(xiM[j]*Fe[k]-xiM[k]*Fe[j])
        e0.append(np.real(Fe[m][ind_mean]))
    curl=np.array(curl)
    curlnorm=np.real(np.sum(curl[:]*np.conj(curl[:])))
    curlnorm=(curlnorm/np.prod(N))**0.5
    norm_e0=np.linalg.norm(e0)
    if norm_e0>1e-10:
        curlnorm=curlnorm/norm_e0
    return curlnorm
예제 #23
0
def curl_norm(e, Y):
    """
    it calculates curl-based norm,
    it controls that the fields are curl-free with zero mean as
    it is required of electric fields

    Parameters
    ----------
        e - electric field
        Y - the size of periodic unit cell

    Returns
    -------
        curlnorm - curl-based norm
    """
    N=np.array(np.shape(e[0]))
    d=np.size(N)
    xil=Grid.get_xil(N, Y)
    xiM=[]
    Fe=[]
    for m in np.arange(d):
        Nshape=np.ones(d)
        Nshape[m]=N[m]
        Nrep=np.copy(N)
        Nrep[m]=1
        xiM.append(np.tile(np.reshape(xil[m], Nshape), Nrep))
        Fe.append(DFT.fftnc(e[m], N)/np.prod(N))

    if d==2:
        Fe.append(np.zeros(N))
        xiM.append(np.zeros(N))

    ind_mean=tuple(np.fix(N/2))
    curl=[]
    e0=[]
    for m in np.arange(3):
        j=(m+1)%3
        k=(j+1)%3
        curl.append(xiM[j]*Fe[k]-xiM[k]*Fe[j])
        e0.append(np.real(Fe[m][ind_mean]))
    curl=np.array(curl)
    curlnorm=np.real(np.sum(curl[:]*np.conj(curl[:])))
    curlnorm=(curlnorm/np.prod(N))**0.5
    norm_e0=np.linalg.norm(e0)
    if norm_e0>1e-10:
        curlnorm=curlnorm/norm_e0
    return curlnorm
예제 #24
0
def elasticity_large_deformation(N, Y, fft_form=fft_form_default):
    N = np.array(N, dtype=np.int)
    dim = N.size
    assert(dim==3)
    freq = Grid.get_freq(N, Y, fft_form=fft_form)
    N_fft=tuple(freq[i].size for i in range(dim))
    Ghat = np.zeros(np.hstack([dim*np.ones(4, dtype=np.int), N_fft]))
    delta  = lambda i,j: np.float(i==j)

    for i, j, k, l in itertools.product(list(range(dim)), repeat=4):
        for x, y, z in np.ndindex(*N_fft):
            q = np.array([freq[0][x], freq[1][y], freq[2][z]])
            if not q.dot(q) == 0:
                Ghat[i,j,k,l,x,y,z] = delta(i,k)*q[j]*q[l] / (q.dot(q))

    Ghat_tensor = Tensor(name='Ghat', val=Ghat, order=4, N=N, multype=42,
                         Fourier=True, fft_form=fft_form)
    return Ghat_tensor
예제 #25
0
def elasticity_large_deformation(N, Y, fft_form=fft_form_default):
    N = np.array(N, dtype=np.int)
    dim = N.size
    assert(dim==3)
    freq = Grid.get_freq(N, Y, fft_form=fft_form)
    N_fft=tuple(freq[i].size for i in range(dim))
    Ghat = np.zeros(np.hstack([dim*np.ones(4, dtype=np.int), N_fft]))
    delta  = lambda i,j: np.float(i==j)

    for i, j, k, l in itertools.product(range(dim), repeat=4):
        for x, y, z in np.ndindex(*N_fft):
            q = np.array([freq[0][x], freq[1][y], freq[2][z]])
            if not q.dot(q) == 0:
                Ghat[i,j,k,l,x,y,z] = delta(i,k)*q[j]*q[l] / (q.dot(q))

    Ghat_tensor = Tensor(name='Ghat', val=Ghat, order=4, N=N, multype=42,
                         Fourier=True, fft_form=fft_form)
    return Ghat_tensor
예제 #26
0
    def plot(self, ind=slice(None), N=None, filen=None, ptype='imshow'):
        if N is None:
            N = self.N

        from mpl_toolkits.mplot3d import axes3d
        import matplotlib.pyplot as plt
        from ffthompy.trigpol import Grid

        coord = Grid.get_coordinates(N, self.Y)

        Z = self.project(N)
        Z = Z.val[ind]
        if self.Fourier:
            Z = np.abs(Z)

        if Z.ndim != 2:
            raise ValueError("The plotting is suited only for dim=2!")

        fig = plt.figure()
        if ptype in ['wireframe']:
            ax = fig.add_subplot(111, projection='3d')
            ax.plot_wireframe(coord[-2], coord[-1], Z)
        elif ptype in ['surface']:
            from matplotlib import cm
            ax = fig.gca(projection='3d')
            surf = ax.plot_surface(coord[-2],
                                   coord[-1],
                                   Z,
                                   rstride=1,
                                   cstride=1,
                                   cmap=cm.coolwarm,
                                   linewidth=0,
                                   antialiased=False)

            fig.colorbar(surf, shrink=0.5, aspect=5)
        elif ptype in ['imshow']:
            ax = plt.imshow(Z)
            plt.colorbar(ax)

        if filen is None:
            plt.show()
        else:
            plt.savefig(filen)
예제 #27
0
def potential(X, small_strain=False):
    if X.Fourier:
        FX=X
    else:
        F=DFT(N=X.N, fft_form=X.fft_form)
        FX=F(X)

    freq=Grid.get_freq(X.N, X.Y, fft_form=FX.fft_form)
    if X.order==1:
        assert(X.dim==X.shape[0])
        iX=Tensor(name='potential({0})'.format(X.name[:10]), shape=(1,), N=X.N,
                  Fourier=True, fft_form=FX.fft_form)
        iX.val[0]=potential_scalar(FX.val, freq=freq, mean_index=FX.mean_index())

    elif X.order==2:
        assert(X.dim==X.shape[0])
        assert(X.dim==X.shape[1])
        iX=Tensor(name='potential({0})'.format(X.name[:10]), shape=(X.dim,), N=X.N,
                  Fourier=True, fft_form=FX.fft_form)
        if not small_strain:
            for ii in range(X.dim):
                iX.val[ii]=potential_scalar(FX.val[ii], freq=freq, mean_index=FX.mean_index())

        else:
            assert((X-X.transpose()).norm()<1e-14) # symmetricity
            omeg=FX.zeros_like() # non-symmetric part of the gradient
            gomeg=Tensor(name='potential({0})'.format(X.name[:10]),
                           shape=FX.shape+(X.dim,), N=X.N, Fourier=True)
            grad_ep=grad(FX) # gradient of strain
            gomeg.val=np.einsum('ikj...->ijk...', grad_ep.val)-np.einsum('jki...->ijk...', grad_ep.val)
            for ij in itertools.product(range(X.dim), repeat=2):
                omeg.val[ij]=potential_scalar(gomeg.val[ij], freq=freq, mean_index=FX.mean_index())

            gradu=FX+omeg
            iX=potential(gradu, small_strain=False)

    if X.Fourier:
        return iX
    else:
        iF=DFT(N=X.N, inverse=True, fft_form=FX.fft_form)
        return iF(iX)
예제 #28
0
    def plot(self, ind=slice(None), N=None, filen=None, ptype='imshow'):
        assert(not self.Fourier)
        if N is None:
            N = self.N

        from mpl_toolkits.mplot3d import axes3d
        import matplotlib.pyplot as plt
        from ffthompy.trigpol import Grid

        coord=Grid.get_coordinates(N, self.Y)

        Z=self.project(N)
        Z = Z.val[ind]

        if Z.ndim != 2:
            raise ValueError("The plotting is suited only for dim=2!")

        fig = plt.figure()
        if ptype in ['wireframe']:
            ax = fig.add_subplot(111, projection='3d')
            ax.plot_wireframe(coord[-2], coord[-1], Z)
        elif ptype in ['surface']:
            from matplotlib import cm
            ax = fig.gca(projection='3d')
            surf = ax.plot_surface(coord[-2], coord[-1], Z,
                                   rstride=1, cstride=1, cmap=cm.coolwarm,
                                   linewidth=0, antialiased=False)

            fig.colorbar(surf, shrink=0.5, aspect=5)
        elif ptype in ['imshow']:
            ax = plt.imshow(Z)
            plt.colorbar(ax)

        if filen is None:
            plt.show()
        else:
            plt.savefig(filen)
예제 #29
0
    def plot(self, ind=0, N=None, filen=None, Y=None, ptype='surface'):
        dim=self.N.size
        if dim!=2:
            raise ValueError("The plotting is suited only for dim=2!")
        if Y is None:
            Y=np.ones(dim)
        if N is None:
            N=self.N

        from mpl_toolkits.mplot3d import axes3d
        import matplotlib.pyplot as plt
        from ffthompy.trigpol import Grid
        fig=plt.figure()
        coord=Grid.get_coordinates(N, Y)
        if np.all(np.greater(N, self.N)):
            Z=DFT.ifftnc(enlarge(DFT.fftnc(self.val[ind], self.N), N), N).real
        elif np.all(np.less(N, self.N)):
            Z=DFT.ifftnc(decrease(DFT.fftnc(self.val[ind], self.N), N), N).real
        elif np.allclose(N, self.N):
            Z=self.val[ind]

        if ptype in ['wireframe']:
            ax=fig.add_subplot(111, projection='3d')
            ax.plot_wireframe(coord[0], coord[1], Z)
        elif ptype in ['surface']:
            from matplotlib import cm
            ax=fig.gca(projection='3d')
            surf=ax.plot_surface(coord[0], coord[1], Z,
                                   rstride=1, cstride=1, cmap=cm.coolwarm,
                                   linewidth=0, antialiased=False)
            fig.colorbar(surf, shrink=0.5, aspect=5)

        if filen is None:
            plt.show()
        else:
            plt.savefig(filen)
예제 #30
0
    def matrix(self):
        """
        This function returns the object as a matrix of DFT or iDFT resp.
        """
        N=self.N
        prodN=np.prod(N)
        proddN=self.d*prodN
        ZNl=Grid.get_ZNl(N, fft_form='c')

        if self.inverse:
            DFTcoef=lambda k, l, N: np.exp(2*np.pi*1j*np.sum(k*l/N))
        else:
            DFTcoef=lambda k, l, N: np.exp(-2*np.pi*1j*np.sum(k*l/N))/np.prod(N)

        DTM=np.zeros([self.pN(), self.pN()], dtype=np.complex128)
        for ii, kk in enumerate(itertools.product(*tuple(ZNl))):
            for jj, ll in enumerate(itertools.product(*tuple(ZNl))):
                DTM[ii, jj]=DFTcoef(np.array(kk, dtype=np.float),
                                      np.array(ll), N)

        DTMd=npmatlib.zeros([proddN, proddN], dtype=np.complex128)
        for ii in range(self.d):
            DTMd[prodN*ii:prodN*(ii+1), prodN*ii:prodN*(ii+1)]=DTM
        return DTMd
예제 #31
0
def grad_tensor(N, Y, kind='TensorTrain'):
    assert(kind.lower() in ['cano','canotensor','tucker','tt','tensortrain'])

    dim=Y.size
    freq=Grid.get_xil(N, Y, fft_form='c')
    hGrad_s=[]

    for ii in range(dim):
        basis=[]
        for jj in range(dim):
            if ii==jj:
                basis.append(np.atleast_2d(freq[jj]*2*np.pi*1j))
            else:
                basis.append(np.atleast_2d(np.ones(N[jj])))

        if kind.lower() in ['cano', 'canotensor','tucker']:
            hGrad_s.append(SparseTensor(kind=kind, name='hGrad({})'.format(ii), core=np.array([1.]),
                                        basis=basis, Fourier=True, fft_form='c').set_fft_form())
        elif kind.lower() in ['tt','tensortrain']:
            cl = [bas.reshape((1,-1,1)) for bas in basis]
            hGrad_s.append(SparseTensor(kind=kind, core=cl, name='hGrad({})'.format(ii),
                                        Fourier=True, fft_form='c').set_fft_form())

    return hGrad_s
예제 #32
0
    def plot(self, ind=0, N=None, filen=None, Y=None, ptype='surface'):
        dim=self.N.size
        if dim!=2:
            raise ValueError("The plotting is suited only for dim=2!")
        if Y is None:
            Y=np.ones(dim)
        if N is None:
            N=self.N

        from mpl_toolkits.mplot3d import axes3d
        import matplotlib.pyplot as plt
        from ffthompy.trigpol import Grid
        fig=plt.figure()
        coord=Grid.get_coordinates(N, Y)
        if np.all(np.greater(N, self.N)):
            Z=DFT.ifftnc(enlarge(DFT.fftnc(self.val[ind], self.N), N), N).real
        elif np.all(np.less(N, self.N)):
            Z=DFT.ifftnc(decrease(DFT.fftnc(self.val[ind], self.N), N), N).real
        elif np.allclose(N, self.N):
            Z=self.val[ind]

        if ptype in ['wireframe']:
            ax=fig.add_subplot(111, projection='3d')
            ax.plot_wireframe(coord[0], coord[1], Z)
        elif ptype in ['surface']:
            from matplotlib import cm
            ax=fig.gca(projection='3d')
            surf=ax.plot_surface(coord[0], coord[1], Z,
                                   rstride=1, cstride=1, cmap=cm.coolwarm,
                                   linewidth=0, antialiased=False)
            fig.colorbar(surf, shrink=0.5, aspect=5)

        if filen is None:
            plt.show()
        else:
            plt.savefig(filen)
예제 #33
0
    def matrix(self):
        """
        This function returns the object as a matrix of DFT or iDFT resp.
        """
        N=self.N
        prodN=np.prod(N)
        proddN=self.d*prodN
        ZNl=Grid.get_ZNl(N, fft_form='c')

        if self.inverse:
            DFTcoef=lambda k, l, N: np.exp(2*np.pi*1j*np.sum(k*l/N))
        else:
            DFTcoef=lambda k, l, N: np.exp(-2*np.pi*1j*np.sum(k*l/N))/np.prod(N)

        DTM=np.zeros([self.pN(), self.pN()], dtype=np.complex128)
        for ii, kk in enumerate(itertools.product(*tuple(ZNl))):
            for jj, ll in enumerate(itertools.product(*tuple(ZNl))):
                DTM[ii, jj]=DFTcoef(np.array(kk, dtype=np.float),
                                      np.array(ll), N)

        DTMd=npmatlib.zeros([proddN, proddN], dtype=np.complex128)
        for ii in range(self.d):
            DTMd[prodN*ii:prodN*(ii+1), prodN*ii:prodN*(ii+1)]=DTM
        return DTMd
예제 #34
0
    def get_A_Ga(self, Nbar, primaldual='primal', order=-1, P=None):
        """
        Returns stiffness matrix for scheme with exact integration.
        """
        if order == -1:
            if 'order' in self.conf:
                order = self.conf['order']
            else:
                raise ValueError('The material order is undefined!')
        elif order not in [None, 'exact', 0, 1]:
            raise ValueError('Wrong material order (%s)!' % str(order))

        if order in [None, 'exact']:  # inclusion-based composite
            shape_funs = self.get_shape_functions(Nbar)
            val = np.zeros(self.conf['vals'][0].shape + shape_funs[0].shape)
            for ii in range(len(self.conf['inclusions'])):
                if primaldual is 'primal':
                    Aincl = self.conf['vals'][ii]
                elif primaldual is 'dual':
                    Aincl = np.linalg.inv(self.conf['vals'][ii])
                val += np.einsum('ij...,k...->ijk...', Aincl, shape_funs[ii])
            name = 'A_Ga'

        else:  # grid-based composite
            if P is None and 'P' in self.conf:
                P = self.conf['P']
            coord = Grid.get_coordinates(P, self.Y)
            vals = self.evaluate(coord)

            if primaldual is 'dual':
                vals = vals.inv()

            h = self.Y / P
            if order in [0, 'constant']:
                Wraw = get_weights_con(h, Nbar, self.Y)
            elif order in [1, 'bilinear']:
                Wraw = get_weights_lin(h, Nbar, self.Y)

            val = np.zeros(vals.shape + tuple(Nbar))
            for m, n in itertools.product(*(list(range(d))
                                            for d in vals.shape)):
                hAM0 = np.prod(P) * cfftnc(vals[m, n], P)
                if np.allclose(P, Nbar):
                    hAM = hAM0
                elif np.all(np.greater_equal(P, Nbar)):
                    hAM = decrease(hAM0, Nbar)
                elif np.all(np.less(P, Nbar)):
                    factor = np.ceil(np.array(Nbar, dtype=np.float64) / 2 / P)
                    hAM0per = np.tile(hAM0,
                                      2 * np.array(factor, dtype=np.int) + 1)
                    hAM = decrease(hAM0per, Nbar)
                else:
                    msg = """This combination of double N (%s) and P (%s) "
                        implemented.""" % (str(Nbar), str(P))
                    raise NotImplementedError(msg)

                val[m, n] = np.real(icfftnc(Wraw * hAM, Nbar))

            name = 'A_Ga_o{0}_P{1}'.format(order, np.array(P).max())

        return Tensor(name=name,
                      val=val,
                      N=Nbar,
                      order=2,
                      Y=self.Y,
                      multype=21,
                      Fourier=False,
                      origin='c').shift()
예제 #35
0
phi_fine = phi.project(M)
print(phi_fine)
print(
    """The procedure is provided by VecTri.enlarge(M) function, which consists of
a calculation of Fourier coefficients, putting zeros to Fourier coefficients
with high frequencies, and inverse FFT that evaluates the polynomial on
a fine grid.
""")

print("""In order to plot this polynomial, we also set a size of a cell
Y =""")
Y = np.ones(d)  # size of a cell
print(Y)
print(""" and evaluate the coordinates of grid points, which are stored in
numpy.ndarray of following shape:
coord.shape =""")
coord = Grid.get_coordinates(M, Y)
print(coord.shape)

if __name__ == "__main__":
    print("""
    Now, the plot of fundamental trigonometric polynomial is shown:""")
    from mpl_toolkits.mplot3d import axes3d
    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.plot_wireframe(coord[0], coord[1], phi_fine.val)
    plt.show()

print('END')
예제 #36
0
phi_fine = phi.project(M)
print(phi_fine)
print("""The procedure is provided by VecTri.enlarge(M) function, which consists of
a calculation of Fourier coefficients, putting zeros to Fourier coefficients
with high frequencies, and inverse FFT that evaluates the polynomial on
a fine grid.
""")


print("""In order to plot this polynomial, we also set a size of a cell
Y =""")
Y = np.ones(d) # size of a cell
print(Y)
print(""" and evaluate the coordinates of grid points, which are stored in
numpy.ndarray of following shape:
coord.shape =""")
coord = Grid.get_coordinates(M, Y)
print(coord.shape)

if __name__ == "__main__":
    print("""
    Now, the plot of fundamental trigonometric polynomial is shown:""")
    from mpl_toolkits.mplot3d import axes3d
    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.plot_wireframe(coord[0], coord[1], phi_fine.val)
    plt.show()

print('END')
예제 #37
0
    def get_A_Ga(self, Nbar, primaldual='primal', order=-1, P=None):
        """
        Returns stiffness matrix for scheme with exact integration.
        """
        if order == -1:
            if 'order' in self.conf:
                order = self.conf['order']
            else:
                raise ValueError('The material order is undefined!')
        elif order not in [None, 'exact', 0, 1]:
            raise ValueError('Wrong material order (%s)!' % str(order))

        if order in [None, 'exact']: # inclusion-based composite
            shape_funs = self.get_shape_functions(Nbar)
            val = np.zeros(self.conf['vals'][0].shape + shape_funs[0].shape)
            for ii in range(len(self.conf['inclusions'])):
                if primaldual is 'primal':
                    Aincl = self.conf['vals'][ii]
                elif primaldual is 'dual':
                    Aincl = np.linalg.inv(self.conf['vals'][ii])
                val += np.einsum('ij...,k...->ijk...', Aincl, shape_funs[ii])
            name = 'A_Ga'

        else: # grid-based composite
            if P is None and 'P' in self.conf:
                P = self.conf['P']
            coord = Grid.get_coordinates(P, self.Y)
            vals = self.evaluate(coord)

            if primaldual is 'dual':
                vals = vals.inv()

            h = self.Y/P
            if order in [0, 'constant']:
                Wraw = get_weights_con(h, Nbar, self.Y)
            elif order in [1, 'bilinear']:
                Wraw = get_weights_lin(h, Nbar, self.Y)

            val = np.zeros(vals.shape+tuple(Nbar))
            for m,n in itertools.product(*(range(d) for d in vals.shape)):
                hAM0 = np.prod(P)*cfftnc(vals[m, n], P)
                if np.allclose(P, Nbar):
                    hAM = hAM0
                elif np.all(np.greater_equal(P, Nbar)):
                    hAM = decrease(hAM0, Nbar)
                elif np.all(np.less(P, Nbar)):
                    factor = np.ceil(np.array(Nbar, dtype=np.float64) / P)
                    hAM0per = np.tile(hAM0,
                                      2*np.array(factor, dtype=np.int)-1)
                    hAM = decrease(hAM0per, Nbar)
                else:
                    msg = """This combination of double N (%s) and P (%s) "
                        implemented.""" % (str(Nbar), str(P))
                    raise NotImplementedError(msg)

                val[m, n] = np.real(icfftnc(Wraw*hAM, Nbar))

            name = 'A_Ga_o{0}_P{1}'.format(order, np.array(P).max())

        return Tensor(name=name, val=val, N=Nbar, order=2, Y=self.Y, multype=21,
                      Fourier=False, origin='c').shift()
예제 #38
0
def scalar(N, Y, NyqNul=True, tensor=True, fft_form=fft_form_default):
    """
    Assembly of discrete kernels in Fourier space for scalar elliptic problems.

    Parameters
    ----------
    N : numpy.ndarray
        no. of discretization points
    Y : numpy.ndarray
        size of periodic unit cell

    Returns
    -------
    G1l : numpy.ndarray
        discrete kernel in Fourier space; provides projection
        on curl-free fields with zero mean
    G2l : numpy.ndarray
        discrete kernel in Fourier space; provides projection
        on divergence-free fields with zero mean
    """
    if fft_form in ['r']:
        fft_form_r = True
        fft_form = 0
    else:
        fft_form_r = False

    d = np.size(N)
    N = np.array(N, dtype=np.int)
    if NyqNul:
        Nred = get_Nodd(N)
    else:
        Nred = N

    xi = Grid.get_xil(Nred, Y, fft_form=fft_form)
    xi2 = []
    for m in np.arange(d):
        xi2.append(xi[m]**2)

    G0l = np.zeros(np.hstack([d, d, Nred]))
    G1l = np.zeros(np.hstack([d, d, Nred]))
    G2l = np.zeros(np.hstack([d, d, Nred]))
    num = np.zeros(np.hstack([d, d, Nred]))
    denom = np.zeros(Nred)

    ind_center = mean_index(Nred, fft_form=fft_form)
    for m in np.arange(d):  # diagonal components
        Nshape = np.ones(d, dtype=np.int)
        Nshape[m] = Nred[m]
        Nrep = np.copy(Nred)
        Nrep[m] = 1
        a = np.reshape(xi2[m], Nshape)
        num[m][m] = np.tile(a, Nrep)  # numerator
        denom = denom + num[m][m]
        G0l[m, m][ind_center] = 1

    for m in np.arange(d):  # upper diagonal components
        for n in np.arange(m + 1, d):
            NshapeM = np.ones(d, dtype=np.int)
            NshapeM[m] = Nred[m]
            NrepM = np.copy(Nred)
            NrepM[m] = 1
            NshapeN = np.ones(d, dtype=np.int)
            NshapeN[n] = Nred[n]
            NrepN = np.copy(Nred)
            NrepN[n] = 1
            num[m][n] = np.tile(np.reshape(xi[m], NshapeM), NrepM) \
                * np.tile(np.reshape(xi[n], NshapeN), NrepN)

    # avoiding a division by zero
    denom[ind_center] = 1

    # calculation of projections
    for m in np.arange(d):
        for n in np.arange(m, d):
            G1l[m][n] = num[m][n] / denom
            G2l[m][n] = (m == n) * np.ones(Nred) - G1l[m][n]
            G2l[m][n][ind_center] = 0

    # symmetrization
    for m in np.arange(1, d):
        for n in np.arange(m):
            G1l[m][n] = G1l[n][m]
            G2l[m][n] = G2l[n][m]

    if tensor:
        G0l = Tensor(name='hG0',
                     val=G0l,
                     order=2,
                     N=N,
                     multype=21,
                     Fourier=True,
                     fft_form=fft_form)
        G1l = Tensor(name='hG1',
                     val=G1l,
                     order=2,
                     N=N,
                     multype=21,
                     Fourier=True,
                     fft_form=fft_form)
        G2l = Tensor(name='hG2',
                     val=G2l,
                     order=2,
                     N=N,
                     multype=21,
                     Fourier=True,
                     fft_form=fft_form)
    else:
        G0l = Matrix(name='hG0', val=G0l, Fourier=True)
        G1l = Matrix(name='hG1', val=G1l, Fourier=True)
        G2l = Matrix(name='hG2', val=G2l, Fourier=True)

    if NyqNul:
        G0l = G0l.enlarge(N)
        G1l = G1l.enlarge(N)
        G2l = G2l.enlarge(N)

    if fft_form_r:
        for tensor in [G0l, G1l, G2l]:
            tensor.set_fft_form(fft_form='r')
            tensor.val /= np.prod(tensor.N)

    return G0l, G1l, G2l
예제 #39
0
def scalar(N, Y, NyqNul=True, tensor=True, fft_form=fft_form_default):
    """
    Assembly of discrete kernels in Fourier space for scalar elliptic problems.

    Parameters
    ----------
    N : numpy.ndarray
        no. of discretization points
    Y : numpy.ndarray
        size of periodic unit cell

    Returns
    -------
    G1l : numpy.ndarray
        discrete kernel in Fourier space; provides projection
        on curl-free fields with zero mean
    G2l : numpy.ndarray
        discrete kernel in Fourier space; provides projection
        on divergence-free fields with zero mean
    """
    if fft_form in ['r']:
        fft_form_r=True
        fft_form=0
    else:
        fft_form_r=False

    d = np.size(N)
    N = np.array(N, dtype=np.int)
    if NyqNul:
        Nred = get_Nodd(N)
    else:
        Nred = N

    xi = Grid.get_xil(Nred, Y, fft_form=fft_form)
    xi2 = []
    for m in np.arange(d):
        xi2.append(xi[m]**2)

    G0l = np.zeros(np.hstack([d, d, Nred]))
    G1l = np.zeros(np.hstack([d, d, Nred]))
    G2l = np.zeros(np.hstack([d, d, Nred]))
    num = np.zeros(np.hstack([d, d, Nred]))
    denom = np.zeros(Nred)

    ind_center = mean_index(Nred, fft_form=fft_form)
    for m in np.arange(d): # diagonal components
        Nshape = np.ones(d, dtype=np.int)
        Nshape[m] = Nred[m]
        Nrep = np.copy(Nred)
        Nrep[m] = 1
        a = np.reshape(xi2[m], Nshape)
        num[m][m] = np.tile(a, Nrep) # numerator
        denom = denom + num[m][m]
        G0l[m, m][ind_center] = 1

    for m in np.arange(d): # upper diagonal components
        for n in np.arange(m+1, d):
            NshapeM = np.ones(d, dtype=np.int)
            NshapeM[m] = Nred[m]
            NrepM = np.copy(Nred)
            NrepM[m] = 1
            NshapeN = np.ones(d, dtype=np.int)
            NshapeN[n] = Nred[n]
            NrepN = np.copy(Nred)
            NrepN[n] = 1
            num[m][n] = np.tile(np.reshape(xi[m], NshapeM), NrepM) \
                * np.tile(np.reshape(xi[n], NshapeN), NrepN)

    # avoiding a division by zero
    denom[ind_center] = 1

    # calculation of projections
    for m in np.arange(d):
        for n in np.arange(m, d):
            G1l[m][n] = num[m][n]/denom
            G2l[m][n] = (m == n)*np.ones(Nred) - G1l[m][n]
            G2l[m][n][ind_center] = 0

    # symmetrization
    for m in np.arange(1, d):
        for n in np.arange(m):
            G1l[m][n] = G1l[n][m]
            G2l[m][n] = G2l[n][m]

    if tensor:
        G0l = Tensor(name='hG0', val=G0l, order=2, N=N, multype=21, Fourier=True, fft_form=fft_form)
        G1l = Tensor(name='hG1', val=G1l, order=2, N=N, multype=21, Fourier=True, fft_form=fft_form)
        G2l = Tensor(name='hG2', val=G2l, order=2, N=N, multype=21, Fourier=True, fft_form=fft_form)
    else:
        G0l = Matrix(name='hG0', val=G0l, Fourier=True)
        G1l = Matrix(name='hG1', val=G1l, Fourier=True)
        G2l = Matrix(name='hG2', val=G2l, Fourier=True)

    if NyqNul:
        G0l = G0l.enlarge(N)
        G1l = G1l.enlarge(N)
        G2l = G2l.enlarge(N)

    if fft_form_r:
        for tensor in [G0l, G1l, G2l]:
            tensor.set_fft_form(fft_form='r')
            tensor.val/=np.prod(tensor.N)

    return G0l, G1l, G2l
예제 #40
0
def elasticity(N, Y, NyqNul=True, tensor=True, fft_form=fft_form_default):
    """
    Projection matrix on a space of admissible strain fields
    INPUT =
        N : ndarray of e.g. stiffness coefficients
        d : dimension; d = 2
        D : dimension in engineering notation; D = 3
        Y : the size of periodic unit cell
    OUTPUT =
        G1h,G1s,G2h,G2s : projection matrices of size DxDxN
    """
    if fft_form in ['r']:
        fft_form_r=True
        fft_form=0
    else:
        fft_form_r=False

    xi = Grid.get_xil(N, Y, fft_form=fft_form)
    N = np.array(N, dtype=np.int)
    d = N.size
    D = int(d*(d+1)/2)

    if NyqNul:
        Nred = get_Nodd(N)
    else:
        Nred = N

    xi2 = []
    for ii in range(d):
        xi2.append(xi[ii]**2)

    num = np.zeros(np.hstack([d, d, Nred]))
    norm2_xi = np.zeros(Nred)
    for mm in np.arange(d): # diagonal components
        Nshape = np.ones(d, dtype=np.int)
        Nshape[mm] = Nred[mm]
        Nrep = np.copy(Nred)
        Nrep[mm] = 1
        num[mm][mm] = np.tile(np.reshape(xi2[mm], Nshape), Nrep) # numerator
        norm2_xi += num[mm][mm]

    norm4_xi = norm2_xi**2
    ind_center = mean_index(Nred, fft_form=fft_form)
    # avoid division by zero
    norm2_xi[ind_center] = 1
    norm4_xi[ind_center] = 1

    for m in np.arange(d): # upper diagonal components
        for n in np.arange(m+1, d):
            NshapeM = np.ones(d, dtype=np.int)
            NshapeM[m] = Nred[m]
            NrepM = np.copy(Nred)
            NrepM[m] = 1
            NshapeN = np.ones(d, dtype=np.int)
            NshapeN[n] = Nred[n]
            NrepN = np.copy(Nred)
            NrepN[n] = 1
            num[m][n] = np.tile(np.reshape(xi[m], NshapeM), NrepM) \
                * np.tile(np.reshape(xi[n], NshapeN), NrepN)

    # G1h = np.zeros([D,D]).tolist()
    G1h = np.zeros(np.hstack([D, D, Nred]))
    G1s = np.zeros(np.hstack([D, D, Nred]))
    IS0 = np.zeros(np.hstack([D, D, Nred]))
    mean = np.zeros(np.hstack([D, D, Nred]))
    Lamh = np.zeros(np.hstack([D, D, Nred]))
    S = np.zeros(np.hstack([D, D, Nred]))
    W = np.zeros(np.hstack([D, D, Nred]))
    WT = np.zeros(np.hstack([D, D, Nred]))

    for m in np.arange(d):
        S[m][m] = 2*num[m][m]/norm2_xi
        for n in np.arange(d):
            G1h[m][n] = num[m][m]*num[n][n]/norm4_xi
            Lamh[m][n] = np.ones(Nred)/d
            Lamh[m][n][ind_center] = 0

    for m in np.arange(D):
        IS0[m][m] = np.ones(Nred)
        IS0[m][m][ind_center] = 0
        mean[m][m][ind_center] = 1

    if d == 2:
        S[0][2] = 2**0.5*num[0][1]/norm2_xi
        S[1][2] = 2**0.5*num[0][1]/norm2_xi
        S[2][2] = np.ones(Nred)
        S[2][2][ind_center] = 0
        G1h[0][2] = 2**0.5*num[0][0]*num[0][1]/norm4_xi
        G1h[1][2] = 2**0.5*num[0][1]*num[1][1]/norm4_xi
        G1h[2][2] = 2*num[0][0]*num[1][1]/norm4_xi
        for m in np.arange(d):
            for n in np.arange(d):
                W[m][n] = num[m][m]/norm2_xi
            W[2][m] = 2**.5*num[0][1]/norm2_xi

    elif d == 3:
        for m in np.arange(d):
            S[m+3][m+3] = 1 - num[m][m]/norm2_xi
            S[m+3][m+3][ind_center] = 0
        for m in np.arange(d):
            for n in np.arange(m+1, d):
                S[m+3][n+3] = num[m][n]/norm2_xi
                G1h[m+3][n+3] = num[m][m]*num[n][n]/norm4_xi
        for m in np.arange(d):
            for n in np.arange(d):
                ind = sp.setdiff1d(np.arange(d), [n])
                S[m][n+3] = (0 == (m == n))*2**.5*num[ind[0]][ind[1]]/norm2_xi
                G1h[m][n+3] = 2**.5*num[m][m]*num[ind[0]][ind[1]]/norm4_xi
                W[m][n] = num[m][m]/norm2_xi
                W[n+3][m] = 2**.5*num[ind[0]][ind[1]]/norm2_xi
        for m in np.arange(d):
            for n in np.arange(d):
                ind_m = sp.setdiff1d(np.arange(d), [m])
                ind_n = sp.setdiff1d(np.arange(d), [n])
                G1h[m+3][n+3] = 2*num[ind_m[0]][ind_m[1]] \
                    * num[ind_n[0]][ind_n[1]] / norm4_xi
    # symmetrization
    for n in np.arange(D):
        for m in np.arange(n+1, D):
            S[m][n] = S[n][m]
            G1h[m][n] = G1h[n][m]
    for m in np.arange(D):
        for n in np.arange(D):
            G1s[m][n] = S[m][n] - 2*G1h[m][n]
            WT[m][n] = W[n][m]
    G2h = 1./(d-1)*(d*Lamh + G1h - W - WT)
    G2s = IS0 - G1h - G1s - G2h

    if tensor:
        G0 = Tensor(name='hG0', val=mean, order=2, N=N, Fourier=True, multype=21, fft_form=fft_form)
        G1h = Tensor(name='hG1h', val=G1h, order=2, N=N, Fourier=True, multype=21, fft_form=fft_form)
        G1s = Tensor(name='hG1s', val=G1s, order=2, N=N, Fourier=True, multype=21, fft_form=fft_form)
        G2h = Tensor(name='hG2h', val=G2h, order=2, N=N, Fourier=True, multype=21, fft_form=fft_form)
        G2s = Tensor(name='hG2s', val=G2s, order=2, N=N, Fourier=True, multype=21, fft_form=fft_form)
    else:
        G0 = Matrix(name='hG0', val=mean, Fourier=True)
        G1h = Matrix(name='hG1h', val=G1h, Fourier=True)
        G1s = Matrix(name='hG1s', val=G1s, Fourier=True)
        G2h = Matrix(name='hG2h', val=G2h, Fourier=True)
        G2s = Matrix(name='hG2s', val=G2s, Fourier=True)

    if NyqNul:
        G0 = G0.enlarge(N)
        G1h = G1h.enlarge(N)
        G1s = G1s.enlarge(N)
        G2h = G2h.enlarge(N)
        G2s = G2s.enlarge(N)

    if fft_form_r:
        for tensor in [G0, G1h, G1s, G2h, G2s]:
            tensor.set_fft_form(fft_form='r')
            tensor.val=1./np.prod(tensor.N)*tensor.val

    return G0, G1h, G1s, G2h, G2s
예제 #41
0
def elasticity(N, Y, NyqNul=True, tensor=True, fft_form=fft_form_default):
    """
    Projection matrix on a space of admissible strain fields
    INPUT =
        N : ndarray of e.g. stiffness coefficients
        d : dimension; d = 2
        D : dimension in engineering notation; D = 3
        Y : the size of periodic unit cell
    OUTPUT =
        G1h,G1s,G2h,G2s : projection matrices of size DxDxN
    """
    if fft_form in ['r']:
        fft_form_r = True
        fft_form = 0
    else:
        fft_form_r = False

    xi = Grid.get_xil(N, Y, fft_form=fft_form)
    N = np.array(N, dtype=np.int)
    d = N.size
    D = int(d * (d + 1) / 2)

    if NyqNul:
        Nred = get_Nodd(N)
    else:
        Nred = N

    xi2 = []
    for ii in range(d):
        xi2.append(xi[ii]**2)

    num = np.zeros(np.hstack([d, d, Nred]))
    norm2_xi = np.zeros(Nred)
    for mm in np.arange(d):  # diagonal components
        Nshape = np.ones(d, dtype=np.int)
        Nshape[mm] = Nred[mm]
        Nrep = np.copy(Nred)
        Nrep[mm] = 1
        num[mm][mm] = np.tile(np.reshape(xi2[mm], Nshape), Nrep)  # numerator
        norm2_xi += num[mm][mm]

    norm4_xi = norm2_xi**2
    ind_center = mean_index(Nred, fft_form=fft_form)
    # avoid division by zero
    norm2_xi[ind_center] = 1
    norm4_xi[ind_center] = 1

    for m in np.arange(d):  # upper diagonal components
        for n in np.arange(m + 1, d):
            NshapeM = np.ones(d, dtype=np.int)
            NshapeM[m] = Nred[m]
            NrepM = np.copy(Nred)
            NrepM[m] = 1
            NshapeN = np.ones(d, dtype=np.int)
            NshapeN[n] = Nred[n]
            NrepN = np.copy(Nred)
            NrepN[n] = 1
            num[m][n] = np.tile(np.reshape(xi[m], NshapeM), NrepM) \
                * np.tile(np.reshape(xi[n], NshapeN), NrepN)

    # G1h = np.zeros([D,D]).tolist()
    G1h = np.zeros(np.hstack([D, D, Nred]))
    G1s = np.zeros(np.hstack([D, D, Nred]))
    IS0 = np.zeros(np.hstack([D, D, Nred]))
    mean = np.zeros(np.hstack([D, D, Nred]))
    Lamh = np.zeros(np.hstack([D, D, Nred]))
    S = np.zeros(np.hstack([D, D, Nred]))
    W = np.zeros(np.hstack([D, D, Nred]))
    WT = np.zeros(np.hstack([D, D, Nred]))

    for m in np.arange(d):
        S[m][m] = 2 * num[m][m] / norm2_xi
        for n in np.arange(d):
            G1h[m][n] = num[m][m] * num[n][n] / norm4_xi
            Lamh[m][n] = np.ones(Nred) / d
            Lamh[m][n][ind_center] = 0

    for m in np.arange(D):
        IS0[m][m] = np.ones(Nred)
        IS0[m][m][ind_center] = 0
        mean[m][m][ind_center] = 1

    if d == 2:
        S[0][2] = 2**0.5 * num[0][1] / norm2_xi
        S[1][2] = 2**0.5 * num[0][1] / norm2_xi
        S[2][2] = np.ones(Nred)
        S[2][2][ind_center] = 0
        G1h[0][2] = 2**0.5 * num[0][0] * num[0][1] / norm4_xi
        G1h[1][2] = 2**0.5 * num[0][1] * num[1][1] / norm4_xi
        G1h[2][2] = 2 * num[0][0] * num[1][1] / norm4_xi
        for m in np.arange(d):
            for n in np.arange(d):
                W[m][n] = num[m][m] / norm2_xi
            W[2][m] = 2**.5 * num[0][1] / norm2_xi

    elif d == 3:
        for m in np.arange(d):
            S[m + 3][m + 3] = 1 - num[m][m] / norm2_xi
            S[m + 3][m + 3][ind_center] = 0
        for m in np.arange(d):
            for n in np.arange(m + 1, d):
                S[m + 3][n + 3] = num[m][n] / norm2_xi
                G1h[m + 3][n + 3] = num[m][m] * num[n][n] / norm4_xi
        for m in np.arange(d):
            for n in np.arange(d):
                ind = sp.setdiff1d(np.arange(d), [n])
                S[m][n +
                     3] = (0 ==
                           (m == n)) * 2**.5 * num[ind[0]][ind[1]] / norm2_xi
                G1h[m][n +
                       3] = 2**.5 * num[m][m] * num[ind[0]][ind[1]] / norm4_xi
                W[m][n] = num[m][m] / norm2_xi
                W[n + 3][m] = 2**.5 * num[ind[0]][ind[1]] / norm2_xi
        for m in np.arange(d):
            for n in np.arange(d):
                ind_m = sp.setdiff1d(np.arange(d), [m])
                ind_n = sp.setdiff1d(np.arange(d), [n])
                G1h[m+3][n+3] = 2*num[ind_m[0]][ind_m[1]] \
                    * num[ind_n[0]][ind_n[1]] / norm4_xi
    # symmetrization
    for n in np.arange(D):
        for m in np.arange(n + 1, D):
            S[m][n] = S[n][m]
            G1h[m][n] = G1h[n][m]
    for m in np.arange(D):
        for n in np.arange(D):
            G1s[m][n] = S[m][n] - 2 * G1h[m][n]
            WT[m][n] = W[n][m]
    G2h = 1. / (d - 1) * (d * Lamh + G1h - W - WT)
    G2s = IS0 - G1h - G1s - G2h

    if tensor:
        G0 = Tensor(name='hG0',
                    val=mean,
                    order=2,
                    N=N,
                    Fourier=True,
                    multype=21,
                    fft_form=fft_form)
        G1h = Tensor(name='hG1h',
                     val=G1h,
                     order=2,
                     N=N,
                     Fourier=True,
                     multype=21,
                     fft_form=fft_form)
        G1s = Tensor(name='hG1s',
                     val=G1s,
                     order=2,
                     N=N,
                     Fourier=True,
                     multype=21,
                     fft_form=fft_form)
        G2h = Tensor(name='hG2h',
                     val=G2h,
                     order=2,
                     N=N,
                     Fourier=True,
                     multype=21,
                     fft_form=fft_form)
        G2s = Tensor(name='hG2s',
                     val=G2s,
                     order=2,
                     N=N,
                     Fourier=True,
                     multype=21,
                     fft_form=fft_form)
    else:
        G0 = Matrix(name='hG0', val=mean, Fourier=True)
        G1h = Matrix(name='hG1h', val=G1h, Fourier=True)
        G1s = Matrix(name='hG1s', val=G1s, Fourier=True)
        G2h = Matrix(name='hG2h', val=G2h, Fourier=True)
        G2s = Matrix(name='hG2s', val=G2s, Fourier=True)

    if NyqNul:
        G0 = G0.enlarge(N)
        G1h = G1h.enlarge(N)
        G1s = G1s.enlarge(N)
        G2h = G2h.enlarge(N)
        G2s = G2s.enlarge(N)

    if fft_form_r:
        for tensor in [G0, G1h, G1s, G2h, G2s]:
            tensor.set_fft_form(fft_form='r')
            tensor.val = 1. / np.prod(tensor.N) * tensor.val

    return G0, G1h, G1s, G2h, G2s