Beispiel #1
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)
    meas_puc = np.prod(Y)
    circ = 0
    for m in np.arange(d):
        Nshape = np.ones(d)
        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 = tuple(np.round(Nbar / 2))
    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
Beispiel #2
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)
    meas_puc = np.prod(Y)
    circ = 0
    for m in np.arange(d):
        Nshape = np.ones(d)
        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 = tuple(np.round(Nbar/2))
    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
Beispiel #3
0
 def get_A_GaNi(self, N, primaldual='primal'):
     """
     Returns stiffness matrix for a scheme with trapezoidal quadrature rule.
     """
     coord = Grid.get_coordinates(N, self.Y)
     A = self.evaluate(coord)
     if primaldual is 'dual':
         A = A.inv()
     return A
Beispiel #4
0
 def get_A_GaNi(self, N, primaldual='primal'):
     """
     Returns stiffness matrix for a scheme with trapezoidal quadrature rule.
     """
     coord = Grid.get_coordinates(N, self.Y)
     A = self.evaluate(coord)
     if primaldual is 'dual':
         A = A.inv()
     return A
Beispiel #5
0
    def get_A_Ga(self, Nbar, primaldual='primal', order=None, P=None):
        """ Returns stiffness matrix for scheme with exact integration."""

        if order is None and 'order' in self.conf:
            order = self.conf['order']

        if order is None:
            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])
            return Matrix(name='A_Ga', val=val, Fourier=False)

        else:
            if P is None and 'P' in self.conf:
                P = self.conf['P']
            coord = Grid.get_coordinates(P, self.Y)
            vals = self.evaluate(coord)
            dim = vals.d
            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)

            Aapp = np.zeros(np.hstack([dim, dim, Nbar]))
            for m in np.arange(dim):
                for n in np.arange(dim):
                    hAM0 = DFT.fftnc(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*factor-1)
                        hAM = decrease(hAM0per, Nbar)
                    else:
                        raise ValueError()

                    pNbar = np.prod(Nbar)
                    """ if DFT is normalized in accordance with articles there
                    should be np.prod(M) instead of np.prod(Nbar)"""
                    Aapp[m, n] = np.real(pNbar*DFT.ifftnc(Wraw*hAM, Nbar))

            name = 'A_Ga_o%d_P%d' % (order, P.max())
            return Matrix(name=name, val=Aapp, Fourier=False)
Beispiel #6
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()
Beispiel #7
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()
Beispiel #8
0
def get_shift_inclusion(N, h, Y):
    N = np.array(N, dtype=np.int32)
    Y = np.array(Y, dtype=np.float64)
    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)
        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
Beispiel #9
0
def get_shift_inclusion(N, h, Y):
    N = np.array(N, dtype=np.int32)
    Y = np.array(Y, dtype=np.float64)
    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)
        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
Beispiel #10
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
Beispiel #11
0
    def matrix(self):
        """
        This function returns the object as a matrix of DFT or iDFT resp.
        """
        prodN = np.prod(self.N)
        proddN = self.d*prodN
        DTM = np.zeros(np.hstack([self.N, self.N]), dtype=np.complex128)
        ZNl = Grid.get_ZNl(self.N)

        if not self.inverse:
            coef = 1./np.prod(self.N)
        else:
            coef = np.prod(self.N)

        for nx in ZNl[0]:
            for ny in ZNl[1]:
                IM = np.zeros(np.array(self.N), dtype=np.float64)
                IM[nx, ny] = 1
                DTM[nx, ny, :, :] = coef*DFT.fftnc(IM, self.N)
        import numpy.matlib as npmatlib
        DTMd = npmatlib.zeros([proddN, proddN], dtype=np.complex128)
        for ii in np.arange(self.d):
            DTMd[prodN*ii:prodN**(ii+1), prodN*ii:prodN**(ii+1)] = DTM
        return DTMd
Beispiel #12
0
def scalar(N, Y, centered=True, NyqNul=True):
    """
    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
    """
    d = np.size(N)
    N = np.array(N)
    if NyqNul:
        Nred = get_Nodd(N)
    else:
        Nred = N

    xi = Grid.get_xil(Nred, Y)
    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 = tuple(np.fix(np.array(Nred)/2))
    for m in np.arange(d): # diagonal components
        Nshape = np.ones(d)
        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)
            NshapeM[m] = Nred[m]
            NrepM = np.copy(Nred)
            NrepM[m] = 1
            NshapeN = np.ones(d)
            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 not centered:
        for m in np.arange(d):
            for n in np.arange(d):
                G1l[m][n] = np.fft.ifftshift(G1l[m][n])
                G2l[m][n] = np.fft.ifftshift(G2l[m][n])

    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)
    return G0l, G1l, G2l
Beispiel #13
0
def elasticity(N, Y, centered=True, NyqNul=True):
    """
    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
    """
    xi = Grid.get_xil(N, Y)
    N = np.array(N)
    d = N.size
    D = d*(d+1)/2

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

    xi2 = []
    for ii in np.arange(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)
        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 = tuple(Nred/2)
    # 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)
            NshapeM[m] = Nred[m]
            NrepM = np.copy(Nred)
            NrepM[m] = 1
            NshapeN = np.ones(d)
            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 not centered:
        for m in np.arange(d):
            for n in np.arange(d):
                G1h[m][n] = np.fft.ifftshift(G1h[m][n])
                G1s[m][n] = np.fft.ifftshift(G1s[m][n])
                G2h[m][n] = np.fft.ifftshift(G2h[m][n])
                G2s[m][n] = np.fft.ifftshift(G2s[m][n])

    G0 = Matrix(name='hG1', val=mean, Fourier=True)
    G1h = Matrix(name='hG1', val=G1h, Fourier=True)
    G1s = Matrix(name='hG1', val=G1s, Fourier=True)
    G2h = Matrix(name='hG1', val=G2h, Fourier=True)
    G2s = Matrix(name='hG1', 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)
    return mean, G1h, G1s, G2h, G2s
Beispiel #14
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']:
            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:
            if P is None and 'P' in self.conf:
                P = self.conf['P']
            coord = Grid.get_coordinates(P, self.Y)
            vals = self.evaluate(coord)
            dim = vals.d
            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(np.hstack([dim, dim, Nbar]))
            for m in np.arange(dim):
                for n in np.arange(dim):
                    hAM0 = DFT.fftnc(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 * factor - 1)
                        hAM = decrease(hAM0per, Nbar)
                    else:
                        raise ValueError()

                    pNbar = np.prod(Nbar)
                    """ if DFT is normalized in accordance with articles there
                    should be np.prod(M) instead of np.prod(Nbar)"""
                    val[m, n] = np.real(pNbar * DFT.ifftnc(Wraw * hAM, Nbar))

            name = 'A_Ga_o%d_P%d' % (order, P.max())

        return Matrix(name=name, val=val, Fourier=False)
Beispiel #15
0
 def get_A_GaNi(self, N, primaldual='primal'):
     coord = Grid.get_coordinates(N, self.Y)
     A = self.evaluate(coord)
     if primaldual is 'dual':
         A = A.inv()
     return A