示例#1
0
    def full(self, **kwargs):
        """convert a tucker representation to a full tensor object
        A = CORE (*1) Basis1 (*2) Basis2 (*3) Basis3 ..., with (*n)  means n-mode product.
        from paper "A MULTILINEAR SINGULAR VALUE DECOMPOSITION" by LIEVEN DE LATHAUWER , BART DE MOOR , AND JOOS VANDEWALLE
        """
        # if core is a single scalar value, make it in a n-D array shape
        if np.prod(self.core.shape) == 1:
            self.core = np.reshape(self.core, tuple(self.r))

        if self.Fourier:
            res = self.fourier()
        else:
            res = self

        val = res.core.copy()
        for i in range(self.order):
            val = nModeProduct(val, res.basis[i].T, i)

        T = Tensor(name=res.name,
                   val=val,
                   order=0,
                   N=val.shape,
                   Fourier=False,
                   **kwargs)

        if self.Fourier:
            T.fourier()

        return T
示例#2
0
    def full(self, **kwargs):
        "return a full tensor object"

        if self.order == 2:
            if self.Fourier:
                res = self.fourier(copy=True)
            else:
                res = self

            # generate Tensor in real domain
            val = np.einsum('i,ik,il->kl', res.core, res.basis[0],
                            res.basis[1])
            kwargsT = dict(name=res.name,
                           val=val,
                           order=0,
                           N=val.shape,
                           Fourier=False,
                           fft_form='c')
            kwargsT.update(kwargs)
            T = Tensor(**kwargsT)

            if self.Fourier:
                T.fourier()
            return T
        else:
            raise NotImplementedError()
示例#3
0
    def test_solvers(self):
        print('\nChecking solvers...')
        dim = 2
        n = 5
        N = n * np.ones(dim, dtype=np.int)

        _, hG1Nt, _ = scalar_tensor(N, Y=np.ones(dim))

        FN = DFT(name='FN', inverse=False, N=N)
        FiN = DFT(name='FiN', inverse=True, N=N)

        G1N = Operator(name='G1', mat=[[FiN, hG1Nt, FN]])

        A = Tensor(name='A',
                   val=np.einsum('ij,...->ij...', np.eye(dim),
                                 1. + 10. * np.random.random(N)),
                   order=2,
                   N=N,
                   multype=21)

        E = np.zeros((dim, ) + dim * (n, ))
        E[0] = 1.  # set macroscopic loading
        E = Tensor(name='E', val=E, order=1, N=N)

        GAfun = Operator(name='GA', mat=[[G1N, A]])
        GAfun.define_operand(E)

        B = GAfun(-E)
        x0 = E.copy(name='x0')
        x0.val[:] = 0

        par = {
            'tol': 1e-10,
            'maxiter': int(1e3),
            'alpha': 0.5 * (1. + 10.),
            'eigrange': [1., 10.]
        }

        # reference solution
        X, _ = linear_solver(Afun=GAfun, B=B, x0=x0, par=par, solver='CG')

        prt.disable()
        for solver in ['CG', 'scipy_cg', 'richardson', 'chebyshev']:
            x, _ = linear_solver(Afun=GAfun,
                                 B=B,
                                 x0=x0,
                                 par=par,
                                 solver=solver)
            self.assertAlmostEqual(0,
                                   norm(X.val - x.val),
                                   delta=1e-8,
                                   msg=solver)
        prt.enable()

        print('...ok')
示例#4
0
def homog_Ga_full_potential(Aga, pars):

    Nbar = Aga.N  # double grid number
    N = np.array((np.array(Nbar) + 1) / 2, dtype=np.int)

    dim = Nbar.__len__()

    F2 = DFT(name='FN', inverse=False,
             N=Nbar)  # discrete Fourier transform (DFT)
    iF2 = DFT(name='FiN', inverse=True, N=Nbar)  # inverse DFT

    P = get_preconditioner(N, pars)

    E = np.zeros(dim)
    E[0] = 1  # macroscopic load
    EN = Tensor(name='EN', N=Nbar, shape=(dim, ),
                Fourier=False)  # constant trig. pol.
    EN.set_mean(E)

    def DFAFGfun(X):
        assert (X.Fourier)
        FAX = F2(Aga * iF2(grad(X).enlarge(Nbar)))
        FAX = FAX.project(N)
        return -div(FAX)

    B = div(F2(Aga(EN)).decrease(N))
    x0 = Tensor(N=N, shape=(),
                Fourier=True)  # initial approximation to solvers

    PDFAFGPfun = lambda Fx: P * DFAFGfun(P * Fx)
    PB = P * B

    tic = Timer(name='CG (potential)')
    iPU, info = linear_solver(solver='CG',
                              Afun=PDFAFGPfun,
                              B=PB,
                              x0=x0,
                              par=pars.solver,
                              callback=None)
    tic.measure()

    print(('iterations of CG={}'.format(info['kit'])))
    print(('norm of residuum={}'.format(info['norm_res'])))
    R = PB - PDFAFGPfun(iPU)
    print(('norm of residuum={} (from definition)'.format(R.norm())))

    Fu = P * iPU
    X = iF2(grad(Fu).project(Nbar))

    AH = Aga(X + EN) * (X + EN)

    return Struct(AH=AH, e=X, Fu=Fu, info=info, time=tic.vals[0][0])
示例#5
0
def get_preconditioner(N, pars):
    hGrad = grad_tensor(N, pars.Y)
    k2 = np.einsum('i...,i...', hGrad.val, np.conj(hGrad.val)).real
    k2[mean_index(N)] = 1.
    return Tensor(name='P',
                  val=1. / k2**0.5,
                  order=0,
                  N=N,
                  Fourier=True,
                  multype=00)
示例#6
0
    def test_solvers(self):
        print('\nChecking solvers...')
        dim=2
        n=5
        N = n*np.ones(dim, dtype=np.int)

        _, hG1Nt, _ = scalar_tensor(N, Y=np.ones(dim))

        FN=DFT(name='FN', inverse=False, N=N)
        FiN=DFT(name='FiN', inverse=True, N=N)

        G1N=Operator(name='G1', mat=[[FiN, hG1Nt, FN]])

        A=Tensor(name='A', val=np.einsum('ij,...->ij...', np.eye(dim), 1.+10.*np.random.random(N)),
                 order=2, N=N, multype=21)

        E=np.zeros((dim,)+dim*(n,)); E[0] = 1. # set macroscopic loading
        E=Tensor(name='E', val=E, order=1, N=N)

        GAfun=Operator(name='GA', mat=[[G1N, A]])
        GAfun.define_operand(E)

        B=GAfun(-E)
        x0=E.copy(name='x0')
        x0.val[:]=0

        par={'tol': 1e-10,
             'maxiter': int(1e3),
             'alpha': 0.5*(1.+10.),
             'eigrange':[1., 10.]}

        # reference solution
        X,_=linear_solver(Afun=GAfun, B=B, x0=x0, par=par, solver='CG')

        prt.disable()
        for solver in ['CG', 'scipy_cg', 'richardson', 'chebyshev']:
            x,_=linear_solver(Afun=GAfun, B=B, x0=x0, par=par, solver=solver)
            self.assertAlmostEqual(0, norm(X.val-x.val), delta=1e-8, msg=solver)
        prt.enable()

        print('...ok')
示例#7
0
 def __call__(self, x):
     self.iter += 1
     if isinstance(x, np.ndarray):
         if isinstance(self.B, VecTri):
             X = VecTri(val=np.reshape(x, self.B.dN()))
         elif isinstance(self.B, VecTri):
             X = Tensor(val=np.reshape(x, self.B.dN()), shape=self.B.shape)
     else:
         X = x
     res = self.B - self.A(X)
     self.res_norm.append(res.norm())
     return
示例#8
0
def homog_Ga_full(Aga, pars):
    Nbar = Aga.N
    N = np.array((np.array(Nbar) + 1) / 2, dtype=np.int)
    dim = Nbar.__len__()
    Y = np.ones(dim)
    _, Ghat, _ = proj.scalar(N, Y)
    Ghat2 = Ghat.enlarge(Nbar)
    F2 = DFT(name='FN', inverse=False,
             N=Nbar)  # discrete Fourier transform (DFT)
    iF2 = DFT(name='FiN', inverse=True, N=Nbar)  # inverse DFT

    G1N = Operator(name='G1', mat=[[iF2, Ghat2,
                                    F2]])  # projection in original space
    PAfun = Operator(name='FiGFA',
                     mat=[[G1N, Aga]])  # lin. operator for a linear system
    E = np.zeros(dim)
    E[0] = 1  # macroscopic load

    EN = Tensor(name='EN', N=Nbar, shape=(dim, ),
                Fourier=False)  # constant trig. pol.
    EN.set_mean(E)

    x0 = Tensor(N=Nbar, shape=(dim, ),
                Fourier=False)  # initial approximation to solvers
    B = PAfun(-EN)  # right-hand side of linear system

    tic = Timer(name='CG (gradient field)')
    X, info = linear_solver(solver='CG',
                            Afun=PAfun,
                            B=B,
                            x0=x0,
                            par=pars.solver,
                            callback=None)
    tic.measure()

    AH = Aga(X + EN) * (X + EN)
    return Struct(AH=AH, X=X, time=tic.vals[0][0], pars=pars)
示例#9
0
    def full(self, **kwargs):
        """
        convert TT to a full tensor object
        """

        if self.Fourier:
            res = self.fourier()
        else:
            res = self

        val = vector.full(res)

        # Tensor with the default fft_form for full tensor
        T = Tensor(name=res.name,
                   val=val,
                   order=0,
                   N=val.shape,
                   Fourier=False,
                   **kwargs)

        if self.Fourier:
            T.fourier()

        return T
示例#10
0
    def evaluate(self, coord, tensor=True):
        """
        Evaluate material at coordinates (coord).

        Parameters
        ----------
        material :
            material definition
        coord : numpy.array
            coordinates where material coefficients are evaluated

        Returns
        -------
        A : numpy.array
            material coefficients at coordinates (coord)
        """
        N = coord.shape[1:]

        if 'fun' in self.conf:
            fun = self.conf['fun']
            A_val = fun(coord)
            shp = A_val.shape[:A_val.ndim - len(N)]
        else:
            shp = self.conf['vals'][0].shape
            A_val = np.zeros(shp + N)
            topos = self.get_topologies(coord)

            astr = 'abcdefgh'
            istr = 'ijklmnopqrst'

            for ii in np.arange(len(self.conf['inclusions'])):
                stroper = '{0},{1}->{0}{1}'.format(astr[:len(shp)],
                                                   istr[:len(N)])
                A_val += np.einsum(stroper, self.conf['vals'][ii], topos[ii])
        if tensor:
            multypes = {'2': 21, '4': 42}
            return Tensor(name='A_GaNi',
                          val=A_val,
                          order=len(shp),
                          N=coord[0].shape,
                          Y=self.Y,
                          multype=multypes['{}'.format(len(shp))],
                          Fourier=False,
                          origin='c')
        else:
            return Matrix(name='A_GaNi', val=A_val, Fourier=False)
示例#11
0
def homog_GaNi_full_potential(Agani, Aga, pars):

    N = Agani.N  # double grid number
    dim = N.__len__()

    F = DFT(name='FN', inverse=False, N=N)  # discrete Fourier transform (DFT)
    iF = DFT(name='FiN', inverse=True, N=N)  # inverse DFT

    P = get_preconditioner(N, pars)

    E = np.zeros(dim)
    E[0] = 1  # macroscopic load
    EN = Tensor(name='EN', N=N, shape=(dim, ),
                Fourier=False)  # constant trig. pol.
    EN.set_mean(E)

    def DFAFGfun(X):
        assert (X.Fourier)
        FAX = F(Agani * iF(grad(X)))
        return -div(FAX)

    B = div(F(Agani(EN)))
    x0 = Tensor(N=N, shape=(),
                Fourier=True)  # initial approximation to solvers

    PDFAFGPfun = lambda Fx: P * DFAFGfun(P * Fx)
    PB = P * B
    tic = Timer(name='CG (potential)')
    iPU, info = linear_solver(solver='CG',
                              Afun=PDFAFGPfun,
                              B=PB,
                              x0=x0,
                              par=pars.solver,
                              callback=None)
    tic.measure()
    print(('iterations of CG={}'.format(info['kit'])))
    print(('norm of residuum={}'.format(info['norm_res'])))

    Fu = P * iPU
    if Aga is None:  # GaNi homogenised properties
        print('!!!!! homogenised properties are GaNi only !!!!!')
        XEN = iF(grad(Fu)) + EN
        AH = Agani(XEN) * XEN
    else:
        Nbar = 2 * np.array(N) - 1
        iF2 = DFT(name='FiN', inverse=True, N=Nbar)  # inverse DFT
        XEN = iF2(grad(Fu).project(Nbar)) + EN.project(Nbar)
        AH = Aga(XEN) * XEN

    return Struct(AH=AH, Fu=Fu, info=info, time=tic.vals[0][0], pars=pars)
示例#12
0
    def test_even(self):
        print('\nChecking Tensors with even grid points...')

        for dim, n, fft_form in itertools.product([2,3], [4,5], fft_forms):
            msg='Tensors with: dim={}, n={}, fft_form={}'.format(dim, n, fft_form)

            N=dim*(n,)
            M=tuple(2*np.array(N))

            u=Tensor(name='test', shape=(), N=N, Fourier=False, fft_form=fft_form)
            u.randomize()
            Fu=u.fourier(copy=True)
            FuM=Fu.project(M)
            uM=FuM.fourier()

            if n%2 == 0:
                self.assertGreaterEqual(u.norm(), FuM.norm(), msg=msg)
                self.assertGreaterEqual(u.norm(componentwise=True), FuM.norm(componentwise=True),
                                       msg=msg)
                self.assertGreaterEqual(u.norm(), uM.norm(), msg=msg)
                self.assertGreaterEqual(u.norm(componentwise=True), uM.norm(componentwise=True),
                                        msg=msg)
            else:
                self.assertAlmostEqual(u.norm(), FuM.norm(), msg=msg)
                self.assertAlmostEqual(u.norm(componentwise=True), FuM.norm(componentwise=True),
                                       msg=msg)
                self.assertAlmostEqual(u.norm(), uM.norm(), msg=msg)
                self.assertAlmostEqual(u.norm(componentwise=True), uM.norm(componentwise=True),
                                        msg=msg)

            self.assertAlmostEqual(0, u.mean()-FuM.mean(), msg=msg)
            self.assertAlmostEqual(u.mean(), uM.mean(), msg=msg)

            # testing that that interpolation on double grid have exactly the same values
            slc=tuple(u.order*[slice(None),]+[slice(0,M[i],2) for i in range(dim)])
            self.assertAlmostEqual(0, np.linalg.norm(u.val-uM.val[slc]), msg=msg)
        print('...ok')
示例#13
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()
示例#14
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
示例#15
0
def elasticity(problem):
    """
    Homogenization of linear elasticity.

    Parameters
    ----------
    problem : object
    """
    print(' ')
    pb = problem
    print(pb)

    # Fourier projections
    _, hG1hN, hG1sN, hG2hN, hG2sN = proj.elasticity(pb.solve['N'], pb.Y, NyqNul=True)
    del _

    if pb.solve['kind'] is 'GaNi':
        Nbar = pb.solve['N']
    elif pb.solve['kind'] is 'Ga':
        Nbar = 2*pb.solve['N'] - 1
        hG1hN = hG1hN.enlarge(Nbar)
        hG1sN = hG1sN.enlarge(Nbar)
        hG2hN = hG2hN.enlarge(Nbar)
        hG2sN = hG2sN.enlarge(Nbar)

    FN = DFT(name='FN', inverse=False, N=Nbar)
    FiN = DFT(name='FiN', inverse=True, N=Nbar)

    G1N = Operator(name='G1', mat=[[FiN, hG1hN + hG1sN, FN]])
    G2N = Operator(name='G2', mat=[[FiN, hG2hN + hG2sN, FN]])

    for primaldual in pb.solve['primaldual']:
        tim = Timer(name='primal-dual')
        print('\nproblem: ' + primaldual)
        solutions = np.zeros(pb.shape).tolist()
        results = np.zeros(pb.shape).tolist()

        # material coefficients
        mat = Material(pb.material)

        if pb.solve['kind'] is 'GaNi':
            A = mat.get_A_GaNi(pb.solve['N'], primaldual)
        elif pb.solve['kind'] is 'Ga':
            A = mat.get_A_Ga(Nbar=Nbar, primaldual=primaldual)

        if primaldual is 'primal':
            GN = G1N
        else:
            GN = G2N

        Afun = Operator(name='FiGFA', mat=[[GN, A]])

        D = int(pb.dim*(pb.dim+1)/2)
        for iL in range(D): # iteration over unitary loads
            E = np.zeros(D)
            E[iL] = 1
            print('macroscopic load E = ' + str(E))
            EN = Tensor(name='EN', N=Nbar, shape=(D,), Fourier=False)
            EN.set_mean(E)
            # initial approximation for solvers
            x0 = EN.zeros_like(name='x0')

            B = Afun(-EN) # RHS

            if not hasattr(pb.solver, 'callback'):
                cb = CallBack(A=Afun, B=B)
            elif pb.solver['callback'] == 'detailed':
                cb = CallBack_GA(A=Afun, B=B, EN=EN, A_Ga=A, GN=GN)
            else:
                raise NotImplementedError("The solver callback (%s) is not \
                    implemented" % (pb.solver['callback']))

            print('solver : %s' % pb.solver['kind'])
            X, info = linear_solver(solver=pb.solver['kind'], Afun=Afun, B=B,
                                    x0=x0, par=pb.solver, callback=cb)

            solutions[iL] = add_macro2minimizer(X, E)
            results[iL] = {'cb': cb, 'info': info}
            print(cb)
        tim.measure()

        # POSTPROCESSING
        del Afun, B, E, EN, GN, X
        postprocess(pb, A, mat, solutions, results, primaldual)
示例#16
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
示例#17
0
    def test_compatibility(self):
        print('\nChecking compatibility...')
        for dim, fft_form in itertools.product([3], fft_forms):
            N = 5 * np.ones(dim, dtype=np.int)
            F = DFT(inverse=False, N=N, fft_form=fft_form)
            iF = DFT(inverse=True, N=N, fft_form=fft_form)

            # scalar problem
            _, G1l, G2l = scalar(N, Y=np.ones(dim), fft_form=fft_form)
            P1 = Operator(name='P1', mat=[[iF, G1l, F]])
            P2 = Operator(name='P2', mat=[[iF, G2l, F]])
            u = Tensor(name='u',
                       shape=(1, ),
                       N=N,
                       Fourier=False,
                       fft_form=fft_form)
            u.randomize()

            grad_u = grad(u)
            self.assertAlmostEqual(0, (P1(grad_u) - grad_u).norm(),
                                   delta=1e-13)
            self.assertAlmostEqual(0, P2(grad_u).norm(), delta=1e-13)

            e = P1(
                Tensor(name='u',
                       shape=(dim, ),
                       N=N,
                       Fourier=False,
                       fft_form=fft_form).randomize())
            e2 = grad(potential(e))
            self.assertAlmostEqual(0, (e - e2).norm(), delta=1e-13)

            # vectorial problem
            hG = elasticity_large_deformation(N=N,
                                              Y=np.ones(dim),
                                              fft_form=fft_form)
            P1 = Operator(name='P', mat=[[iF, hG, F]])
            u = Tensor(name='u',
                       shape=(dim, ),
                       N=N,
                       Fourier=False,
                       fft_form=fft_form)
            u.randomize()
            grad_u = grad(u)
            val = (P1(grad_u) - grad_u).norm()
            self.assertAlmostEqual(0, val, delta=1e-13)

            e = Tensor(name='F',
                       shape=(dim, dim),
                       N=N,
                       Fourier=False,
                       fft_form=fft_form)
            e = P1(e.randomize())
            e2 = grad(potential(e))
            self.assertAlmostEqual(0, (e - e2).norm(), delta=1e-13)

            # transpose
            P1TT = P1.transpose().transpose()
            self.assertTrue(P1(grad_u) == P1TT(grad_u))

            self.assertTrue(hG == (hG.transpose_left().transpose_left()))
            self.assertTrue(hG == (hG.transpose_right().transpose_right()))

            # vectorial problem - symetric gradient
            hG = elasticity_small_strain(N=N,
                                         Y=np.ones(dim),
                                         fft_form=fft_form)
            P1 = Operator(name='P', mat=[[iF, hG, F]])
            u = Tensor(name='u',
                       shape=(dim, ),
                       N=N,
                       Fourier=False,
                       fft_form=fft_form)
            u.randomize()
            grad_u = symgrad(u)
            val = (P1(grad_u) - grad_u).norm()
            self.assertAlmostEqual(0, val, delta=1e-13)

            e = Tensor(name='strain',
                       shape=(dim, dim),
                       N=N,
                       Fourier=False,
                       fft_form=fft_form)
            e = P1(e.randomize())
            e2 = symgrad(potential(e, small_strain=True))
            self.assertAlmostEqual(0, (e - e2).norm(), delta=1e-13)

            # means
            Fu = F(u)
            E = np.random.random(u.shape)
            u.set_mean(E)
            self.assertAlmostEqual(0, norm(u.mean() - E), delta=1e-13)
            Fu.set_mean(E)
            self.assertAlmostEqual(0, norm(Fu.mean() - E), delta=1e-13)

            # __repr__
            prt.disable()
            print(P1)
            print(u)
            prt.enable()
            self.assertAlmostEqual(0, (P1 == P1.transpose()), delta=1e-13)
        print('...ok')
示例#18
0
    def test_even(self):
        print('\nChecking Tensors with even grid points...')

        for dim, n, fft_form in itertools.product([2, 3], [4, 5], fft_forms):
            msg = 'Tensors with: dim={}, n={}, fft_form={}'.format(
                dim, n, fft_form)

            N = dim * (n, )
            M = tuple(2 * np.array(N))

            u = Tensor(name='test',
                       shape=(),
                       N=N,
                       Fourier=False,
                       fft_form=fft_form)
            u.randomize()
            Fu = u.fourier(copy=True)
            FuM = Fu.project(M)
            uM = FuM.fourier()

            if n % 2 == 0:
                self.assertGreaterEqual(u.norm(), FuM.norm(), msg=msg)
                self.assertGreaterEqual(u.norm(componentwise=True),
                                        FuM.norm(componentwise=True),
                                        msg=msg)
                self.assertGreaterEqual(u.norm(), uM.norm(), msg=msg)
                self.assertGreaterEqual(u.norm(componentwise=True),
                                        uM.norm(componentwise=True),
                                        msg=msg)
            else:
                self.assertAlmostEqual(u.norm(), FuM.norm(), msg=msg)
                self.assertAlmostEqual(u.norm(componentwise=True),
                                       FuM.norm(componentwise=True),
                                       msg=msg)
                self.assertAlmostEqual(u.norm(), uM.norm(), msg=msg)
                self.assertAlmostEqual(u.norm(componentwise=True),
                                       uM.norm(componentwise=True),
                                       msg=msg)

            self.assertAlmostEqual(0, u.mean() - FuM.mean(), msg=msg)
            self.assertAlmostEqual(u.mean(), uM.mean(), msg=msg)

            # testing that that interpolation on double grid have exactly the same values
            slc = tuple(u.order * [
                slice(None),
            ] + [slice(0, M[i], 2) for i in range(dim)])
            self.assertAlmostEqual(0,
                                   np.linalg.norm(u.val - uM.val[slc]),
                                   msg=msg)
        print('...ok')
示例#19
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
示例#20
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
示例#21
0
      'postprocess': [{'kind': 'GaNi'}],
      'solver': {'kind': 'CG',
                 'tol': 1e-8,
                 'maxiter': 1e3}}

print("""
The material properties for FFT-based homogenization are stored at grid
points and are represented with class 'Matrix',
which has the same or similar attributes and methods as a VecTri class
from 'tutorial_01.py'. In order to show its application, we create a material
coefficients composed of random values, symmetrize them, and sum them with
a multiplication of identity to obtain positive definite matrix, i.e.
A =""")
from ffthompy.tensors import Tensor
D = int(dim*(dim+1)/2)
A = Tensor(N=N, shape=(D,D), Fourier=False, multype=21)
A.randomize()
A = A + A.transpose() # symmetrization
# adding a multiplication of identity matrix:
I = Tensor(N=N, shape=(D,D), Fourier=False, multype=21)
I.identity()
A += 3*I
A.name='material'
print(A)

print("""
The values of material coefficients are stored in 'self.val', which is
'numpy.ndarray' object of shape = (D, D) + tuple(N)
here D=d*(d+1)/2 is a number of components of elasticity matrix in
engineering notation, so
A.val.shape =""")
示例#22
0
from ffthompy.tensors import Tensor, DFT

print("""
The work with trigonometric polynomials is shown for""")
d = 2
N = 5*np.ones(d, dtype=np.int32)
print('dimension d =', d)
print('number of grid points N =', N)
print('which is implemented as a numpy.ndarray.')

print("""
Particularly, the vector-valued trigonometric polynomial is created as an instance 'xN' of class
'Tensor' and the random values are assigned.
""")

xN = Tensor(name='trigpol_rand', shape=(d,), N=N)
xN.randomize()

print("""
Basic properties of a trigonometric polynomials can be printed with a norm
corresponding to L2 norm of trigonometric polynomial, i.e.
xN =""")
print(xN)

print("""
The values of trigonometric polynomials are stored in atribute val of type
numpy.ndarray with shape = (self.d,) + tuple(self.N), i.e.
xN.val.shape =""")
print(xN.val.shape)
print("xN.val = xN[:] =")
print(xN.val)
A = mat.get_A_Ga(Nbar=Nbar, primaldual=pb['solve']['primaldual'][0])

# projections in Fourier space
_, hG1N, _ = proj.scalar(pb['solve']['N'], pb['material']['Y'], NyqNul=True, tensor=True)
# increasing the projection with zeros to comply with a projection
# on double grid, see Definition 24 in IJNME2016
hG1N = hG1N.enlarge(Nbar)

FN = DFT(name='FN', inverse=False, N=Nbar) # discrete Fourier transform (DFT)
FiN = DFT(name='FiN', inverse=True, N=Nbar) # inverse DFT

G1N = Operator(name='G1', mat=[[FiN, hG1N, FN]]) # projection in original space
Afun = Operator(name='FiGFA', mat=[[G1N, A]]) # lin. operator for a linear system

E = np.zeros(dim); E[0] = 1 # macroscopic load
EN = Tensor(name='EN', N=Nbar, shape=(dim,), Fourier=False) # constant trig. pol.
EN.set_mean(E)

x0 = Tensor(N=Nbar, shape=(dim,), Fourier=False) # initial approximation to solvers
B = Afun(-EN) # right-hand side of linear system

X, info = linear_solver(solver='CG', Afun=Afun, B=B,
                        x0=x0, par=pb['solver'], callback=None)

print('homogenised properties (component 11) =', A(X + EN)*(X + EN))

if __name__ == "__main__":
    ## plotting of local fields ##################
    X.plot(ind=0, N=N)

print('END')
示例#24
0
    def test_Fourier(self):
        print('\nChecking Fourier functions ...')

        for opt in [0, 'c']:

            a = SparseTensor(kind='cano', val=self.T2d, fft_form=opt)
            T = Tensor(val=self.T2d,
                       order=0,
                       N=self.T2d.shape,
                       Fourier=False,
                       fft_form=opt)
            self.assertAlmostEqual(
                norm(a.fourier().full(fft_form=opt).val -
                     T.fourier(copy=True).val), 0)
            self.assertEqual(
                norm(a.fourier().fourier(real_output=True).full().val.imag), 0)

            a = SparseTensor(kind='tucker', val=self.T3d, fft_form=opt)
            T = Tensor(val=self.T3d,
                       order=0,
                       N=self.T3d.shape,
                       Fourier=False,
                       fft_form=opt)
            self.assertAlmostEqual(
                norm(a.fourier().full(fft_form=opt) - T.fourier(copy=True)), 0)
            self.assertEqual(
                norm(a.fourier().fourier(real_output=True).full().val.imag), 0)

            a = SparseTensor(kind='tt', val=self.T3d, fft_form=opt)
            T = Tensor(val=self.T3d,
                       order=0,
                       N=self.T3d.shape,
                       Fourier=False,
                       fft_form=opt)
            self.assertAlmostEqual(
                norm(a.fourier().full(fft_form=opt) -
                     T.fourier(copy=True).val), 0)
            self.assertEqual(
                norm(a.fourier().fourier(real_output=True).full().val.imag), 0)
        # checking shifting fft_forms
        sparse_opt = 'sr'
        for full_opt in [0, 'c']:

            a = SparseTensor(kind='cano', val=self.T2d, fft_form=sparse_opt)
            T = Tensor(val=self.T2d,
                       order=0,
                       N=self.T2d.shape,
                       Fourier=False,
                       fft_form=full_opt)
            self.assertAlmostEqual(
                norm(a.fourier().full(fft_form=full_opt) -
                     T.fourier(copy=True)), 0)
            self.assertAlmostEqual((a.fourier().set_fft_form(full_opt) -
                                    a.set_fft_form(full_opt).fourier()).norm(),
                                   0)

            a = SparseTensor(kind='tucker', val=self.T3d, fft_form=sparse_opt)
            T = Tensor(val=self.T3d,
                       order=0,
                       N=self.T3d.shape,
                       Fourier=False,
                       fft_form=full_opt)
            self.assertAlmostEqual(
                norm(a.fourier().full(fft_form=full_opt) -
                     T.fourier(copy=True)), 0)
            self.assertAlmostEqual((a.fourier().set_fft_form(full_opt) -
                                    a.set_fft_form(full_opt).fourier()).norm(),
                                   0)

            a = SparseTensor(kind='tt', val=self.T3d, fft_form=sparse_opt)
            T = Tensor(val=self.T3d,
                       order=0,
                       N=self.T3d.shape,
                       Fourier=False,
                       fft_form=full_opt)
            self.assertAlmostEqual(
                norm(a.fourier().full(fft_form=full_opt) -
                     T.fourier(copy=True)), 0)
            self.assertAlmostEqual((a.fourier().set_fft_form(full_opt) -
                                    a.set_fft_form(full_opt).fourier()).norm(),
                                   0)

        print('...ok')
示例#25
0
from ffthompy.tensors import Tensor, DFT

print("""
The work with trigonometric polynomials is shown for""")
d = 2
N = 5 * np.ones(d, dtype=np.int32)
print('dimension d =', d)
print('number of grid points N =', N)
print('which is implemented as a numpy.ndarray.')

print("""
Particularly, the vector-valued trigonometric polynomial is created as an instance 'xN' of class
'Tensor' and the random values are assigned.
""")

xN = Tensor(name='trigpol_rand', shape=(d, ), N=N)
xN.randomize()

print("""
Basic properties of a trigonometric polynomials can be printed with a norm
corresponding to L2 norm of trigonometric polynomial, i.e.
xN =""")
print(xN)

print("""
The values of trigonometric polynomials are stored in atribute val of type
numpy.ndarray with shape = (self.d,) + tuple(self.N), i.e.
xN.val.shape =""")
print(xN.val.shape)
print("xN.val = xN[:] =")
print(xN.val)
示例#26
0
    def test_operators(self):
        print('\nChecking operators...')
        for dim, fft_form in itertools.product([2, 3], fft_forms):
            N = 5 * np.ones(dim, dtype=np.int)
            F = DFT(N=N, inverse=False, fft_form=fft_form)
            iF = DFT(N=N, inverse=True, fft_form=fft_form)

            # Fourier transform
            prt.disable()
            print(F)  # checking representation
            prt.enable()

            u = Tensor(name='u',
                       shape=(),
                       N=N,
                       Fourier=False,
                       fft_form=fft_form).randomize()
            Fu = F(u)
            u2 = iF(Fu)
            self.assertAlmostEqual(0, (u == u2)[1],
                                   delta=1e-13,
                                   msg='Fourier transform')

            fft_formsC = copy(fft_forms)
            fft_formsC.remove(fft_form)
            for fft_formc in fft_formsC:
                FuC = Fu.set_fft_form(fft_formc, copy=True)
                Fu2 = FuC.set_fft_form(fft_form, copy=True)
                msg = 'Tensor.set_fft_form()'
                self.assertAlmostEqual(0,
                                       Fu.norm() - FuC.norm(),
                                       delta=1e-13,
                                       msg=msg)
                self.assertAlmostEqual(0,
                                       norm(Fu.mean() - FuC.mean()),
                                       delta=1e-13,
                                       msg=msg)
                self.assertAlmostEqual(0, (Fu == Fu2)[1], delta=1e-13, msg=msg)

            # scalar problem
            u = Tensor(name='u',
                       shape=(1, ),
                       N=N,
                       Fourier=False,
                       fft_form=fft_form).randomize()
            u.val -= np.mean(u.val)
            Fu = F(u)
            Fu2 = potential(grad(Fu))
            self.assertAlmostEqual(0, (Fu == Fu2)[1],
                                   delta=1e-13,
                                   msg='scalar problem, Fourier=True')

            u2 = potential(grad(u))
            self.assertAlmostEqual(0, (u == u2)[1],
                                   delta=1e-13,
                                   msg='scalar problem, Fourier=False')

            hG, hD = grad_div_tensor(N, fft_form=fft_form)
            self.assertAlmostEqual(0, (hD(hG(Fu)) == div(grad(Fu)))[1],
                                   delta=1e-13,
                                   msg='scalar problem, Fourier=True')

            # vectorial problem
            u = Tensor(name='u',
                       shape=(dim, ),
                       N=N,
                       Fourier=False,
                       fft_form=fft_form)
            u.randomize()
            u.add_mean(-u.mean())

            Fu = F(u)
            Fu2 = potential(grad(Fu))
            self.assertAlmostEqual(0, (Fu == Fu2)[1],
                                   delta=1e-13,
                                   msg='vectorial problem, Fourier=True')

            u2 = potential(grad(u))
            self.assertAlmostEqual(0, (u == u2)[1],
                                   delta=1e-13,
                                   msg='vectorial problem, Fourier=False')

            # 'vectorial problem - symetric gradient
            Fu2 = potential(symgrad(Fu), small_strain=True)
            self.assertAlmostEqual(0, (Fu == Fu2)[1],
                                   delta=1e-13,
                                   msg='vectorial - sym, Fourier=True')

            u2 = potential(symgrad(u), small_strain=True)
            self.assertAlmostEqual(0, (u == u2)[1],
                                   delta=1e-13,
                                   msg='vectorial - sym, Fourier=False')

            # matrix version of DFT
            u = Tensor(name='u', shape=(1, ), N=N, Fourier=False,
                       fft_form='c').randomize()
            F = DFT(N=N, inverse=False, fft_form='c')
            Fu = F(u)
            dft = F.matrix(shape=u.shape)
            Fu2 = dft.dot(u.val.ravel())
            self.assertAlmostEqual(0, norm(Fu.val.ravel() - Fu2), delta=1e-13)

        print('...ok')
示例#27
0
    def test_compatibility(self):
        print('\nChecking compatibility...')
        for dim, fft_form in itertools.product([3], fft_forms):
            N=5*np.ones(dim, dtype=np.int)
            F=DFT(inverse=False, N=N, fft_form=fft_form)
            iF=DFT(inverse=True, N=N, fft_form=fft_form)

            # scalar problem
            _, G1l, G2l=scalar(N, Y=np.ones(dim), fft_form=fft_form)
            P1=Operator(name='P1', mat=[[iF, G1l, F]])
            P2=Operator(name='P2', mat=[[iF, G2l, F]])
            u=Tensor(name='u', shape=(1,), N=N, Fourier=False, fft_form=fft_form)
            u.randomize()

            grad_u=grad(u)
            self.assertAlmostEqual(0, (P1(grad_u)-grad_u).norm(), delta=1e-13)
            self.assertAlmostEqual(0, P2(grad_u).norm(), delta=1e-13)

            e=P1(Tensor(name='u', shape=(dim,), N=N,
                          Fourier=False, fft_form=fft_form).randomize())
            e2=grad(potential(e))
            self.assertAlmostEqual(0, (e-e2).norm(), delta=1e-13)

            # vectorial problem
            hG=elasticity_large_deformation(N=N, Y=np.ones(dim), fft_form=fft_form)
            P1=Operator(name='P', mat=[[iF, hG, F]])
            u=Tensor(name='u', shape=(dim,), N=N, Fourier=False, fft_form=fft_form)
            u.randomize()
            grad_u=grad(u)
            val=(P1(grad_u)-grad_u).norm()
            self.assertAlmostEqual(0, val, delta=1e-13)

            e=Tensor(name='F', shape=(dim, dim), N=N, Fourier=False, fft_form=fft_form)
            e=P1(e.randomize())
            e2=grad(potential(e))
            self.assertAlmostEqual(0, (e-e2).norm(), delta=1e-13)

            # transpose
            P1TT=P1.transpose().transpose()
            self.assertTrue(P1(grad_u)==P1TT(grad_u))

            self.assertTrue(hG==(hG.transpose_left().transpose_left()))
            self.assertTrue(hG==(hG.transpose_right().transpose_right()))

            # vectorial problem - symetric gradient
            hG=elasticity_small_strain(N=N, Y=np.ones(dim), fft_form=fft_form)
            P1=Operator(name='P', mat=[[iF, hG, F]])
            u=Tensor(name='u', shape=(dim,), N=N, Fourier=False, fft_form=fft_form)
            u.randomize()
            grad_u=symgrad(u)
            val=(P1(grad_u)-grad_u).norm()
            self.assertAlmostEqual(0, val, delta=1e-13)

            e=Tensor(name='strain', shape=(dim, dim), N=N,
                     Fourier=False, fft_form=fft_form)
            e=P1(e.randomize())
            e2=symgrad(potential(e, small_strain=True))
            self.assertAlmostEqual(0, (e-e2).norm(), delta=1e-13)

            # means
            Fu=F(u)
            E=np.random.random(u.shape)
            u.set_mean(E)
            self.assertAlmostEqual(0, norm(u.mean()-E), delta=1e-13)
            Fu.set_mean(E)
            self.assertAlmostEqual(0, norm(Fu.mean()-E), delta=1e-13)

            # __repr__
            prt.disable()
            print(P1)
            print(u)
            prt.enable()
            self.assertAlmostEqual(0, (P1==P1.transpose()), delta=1e-13)
        print('...ok')
示例#28
0
def elasticity(problem):
    """
    Homogenization of linear elasticity.

    Parameters
    ----------
    problem : object
    """
    print(' ')
    pb = problem
    print(pb)

    # Fourier projections
    _, hG1hN, hG1sN, hG2hN, hG2sN = proj.elasticity(pb.solve['N'],
                                                    pb.Y,
                                                    NyqNul=True)
    del _

    if pb.solve['kind'] is 'GaNi':
        Nbar = pb.solve['N']
    elif pb.solve['kind'] is 'Ga':
        Nbar = 2 * pb.solve['N'] - 1
        hG1hN = hG1hN.enlarge(Nbar)
        hG1sN = hG1sN.enlarge(Nbar)
        hG2hN = hG2hN.enlarge(Nbar)
        hG2sN = hG2sN.enlarge(Nbar)

    FN = DFT(name='FN', inverse=False, N=Nbar)
    FiN = DFT(name='FiN', inverse=True, N=Nbar)

    G1N = Operator(name='G1', mat=[[FiN, hG1hN + hG1sN, FN]])
    G2N = Operator(name='G2', mat=[[FiN, hG2hN + hG2sN, FN]])

    for primaldual in pb.solve['primaldual']:
        tim = Timer(name='primal-dual')
        print(('\nproblem: ' + primaldual))
        solutions = np.zeros(pb.shape).tolist()
        results = np.zeros(pb.shape).tolist()

        # material coefficients
        mat = Material(pb.material)

        if pb.solve['kind'] is 'GaNi':
            A = mat.get_A_GaNi(pb.solve['N'], primaldual)
        elif pb.solve['kind'] is 'Ga':
            A = mat.get_A_Ga(Nbar=Nbar, primaldual=primaldual)

        if primaldual is 'primal':
            GN = G1N
        else:
            GN = G2N

        Afun = Operator(name='FiGFA', mat=[[GN, A]])

        D = int(pb.dim * (pb.dim + 1) / 2)
        for iL in range(D):  # iteration over unitary loads
            E = np.zeros(D)
            E[iL] = 1
            print(('macroscopic load E = ' + str(E)))
            EN = Tensor(name='EN', N=Nbar, shape=(D, ), Fourier=False)
            EN.set_mean(E)
            # initial approximation for solvers
            x0 = EN.zeros_like(name='x0')

            B = Afun(-EN)  # RHS

            if not hasattr(pb.solver, 'callback'):
                cb = CallBack(A=Afun, B=B)
            elif pb.solver['callback'] == 'detailed':
                cb = CallBack_GA(A=Afun, B=B, EN=EN, A_Ga=A, GN=GN)
            else:
                raise NotImplementedError("The solver callback (%s) is not \
                    implemented" % (pb.solver['callback']))

            print(('solver : %s' % pb.solver['kind']))
            X, info = linear_solver(solver=pb.solver['kind'],
                                    Afun=Afun,
                                    B=B,
                                    x0=x0,
                                    par=pb.solver,
                                    callback=cb)

            solutions[iL] = add_macro2minimizer(X, E)
            results[iL] = {'cb': cb, 'info': info}
            print(cb)
        tim.measure()

        # POSTPROCESSING
        del Afun, B, E, EN, GN, X
        postprocess(pb, A, mat, solutions, results, primaldual)
示例#29
0
    def test_operators(self):
        print('\nChecking operators...')
        for dim, fft_form in itertools.product([2, 3], fft_forms):
            N=5*np.ones(dim, dtype=np.int)
            F=DFT(N=N, inverse=False, fft_form=fft_form)
            iF=DFT(N=N, inverse=True, fft_form=fft_form)

            # Fourier transform
            prt.disable()
            print(F) # checking representation
            prt.enable()

            u=Tensor(name='u', shape=(), N=N, Fourier=False,
                       fft_form=fft_form).randomize()
            Fu=F(u)
            u2=iF(Fu)
            self.assertAlmostEqual(0, (u==u2)[1], delta=1e-13, msg='Fourier transform')

            fft_formsC=copy(fft_forms)
            fft_formsC.remove(fft_form)
            for fft_formc in fft_formsC:
                FuC=Fu.set_fft_form(fft_formc, copy=True)
                Fu2=FuC.set_fft_form(fft_form, copy=True)
                msg='Tensor.set_fft_form()'
                self.assertAlmostEqual(0, Fu.norm()-FuC.norm(), delta=1e-13, msg=msg)
                self.assertAlmostEqual(0, norm(Fu.mean()-FuC.mean()), delta=1e-13, msg=msg)
                self.assertAlmostEqual(0, (Fu==Fu2)[1], delta=1e-13, msg=msg)

            # scalar problem
            u=Tensor(name='u', shape=(1,), N=N, Fourier=False,
                       fft_form=fft_form).randomize()
            u.val-=np.mean(u.val)
            Fu=F(u)
            Fu2=potential(grad(Fu))
            self.assertAlmostEqual(0, (Fu==Fu2)[1], delta=1e-13,
                                   msg='scalar problem, Fourier=True')

            u2=potential(grad(u))
            self.assertAlmostEqual(0, (u==u2)[1], delta=1e-13,
                                   msg='scalar problem, Fourier=False')

            hG, hD=grad_div_tensor(N, fft_form=fft_form)
            self.assertAlmostEqual(0, (hD(hG(Fu))==div(grad(Fu)))[1], delta=1e-13,
                                   msg='scalar problem, Fourier=True')

            # vectorial problem
            u=Tensor(name='u', shape=(dim,), N=N, Fourier=False, fft_form=fft_form)
            u.randomize()
            u.add_mean(-u.mean())

            Fu=F(u)
            Fu2=potential(grad(Fu))
            self.assertAlmostEqual(0, (Fu==Fu2)[1], delta=1e-13,
                                   msg='vectorial problem, Fourier=True')

            u2=potential(grad(u))
            self.assertAlmostEqual(0, (u==u2)[1], delta=1e-13,
                                   msg='vectorial problem, Fourier=False')

            # 'vectorial problem - symetric gradient
            Fu2=potential(symgrad(Fu), small_strain=True)
            self.assertAlmostEqual(0, (Fu==Fu2)[1], delta=1e-13,
                                   msg='vectorial - sym, Fourier=True')

            u2=potential(symgrad(u), small_strain=True)
            self.assertAlmostEqual(0, (u==u2)[1], delta=1e-13,
                                   msg='vectorial - sym, Fourier=False')

            # matrix version of DFT
            u=Tensor(name='u', shape=(1,), N=N, Fourier=False,
                       fft_form='c').randomize()
            F=DFT(N=N, inverse=False, fft_form='c')
            Fu=F(u)
            dft=F.matrix(shape=u.shape)
            Fu2=dft.dot(u.val.ravel())
            self.assertAlmostEqual(0, norm(Fu.val.ravel()-Fu2), delta=1e-13)

        print('...ok')
示例#30
0
        'tol': 1e-8,
        'maxiter': 1e3
    }
}

print("""
The material properties for FFT-based homogenization are stored at grid
points and are represented with class 'Matrix',
which has the same or similar attributes and methods as a VecTri class
from 'tutorial_01.py'. In order to show its application, we create a material
coefficients composed of random values, symmetrize them, and sum them with
a multiplication of identity to obtain positive definite matrix, i.e.
A =""")
from ffthompy.tensors import Tensor
D = int(dim * (dim + 1) / 2)
A = Tensor(N=N, shape=(D, D), Fourier=False, multype=21)
A.randomize()
A = A + A.transpose()  # symmetrization
# adding a multiplication of identity matrix:
I = Tensor(N=N, shape=(D, D), Fourier=False, multype=21)
I.identity()
A += 3 * I
A.name = 'material'
print(A)

print("""
The values of material coefficients are stored in 'self.val', which is
'numpy.ndarray' object of shape = (D, D) + tuple(N)
here D=d*(d+1)/2 is a number of components of elasticity matrix in
engineering notation, so
A.val.shape =""")
示例#31
0
                         tensor=True)
# increasing the projection with zeros to comply with a projection
# on double grid, see Definition 24 in IJNME2016
hG1N = hG1N.enlarge(Nbar)

FN = DFT(name='FN', inverse=False, N=Nbar)  # discrete Fourier transform (DFT)
FiN = DFT(name='FiN', inverse=True, N=Nbar)  # inverse DFT

G1N = Operator(name='G1', mat=[[FiN, hG1N,
                                FN]])  # projection in original space
Afun = Operator(name='FiGFA', mat=[[G1N,
                                    A]])  # lin. operator for a linear system

E = np.zeros(dim)
E[0] = 1  # macroscopic load
EN = Tensor(name='EN', N=Nbar, shape=(dim, ),
            Fourier=False)  # constant trig. pol.
EN.set_mean(E)

x0 = Tensor(N=Nbar, shape=(dim, ),
            Fourier=False)  # initial approximation to solvers
B = Afun(-EN)  # right-hand side of linear system

X, info = linear_solver(solver='CG',
                        Afun=Afun,
                        B=B,
                        x0=x0,
                        par=pb['solver'],
                        callback=None)

print('homogenised properties (component 11) =', A(X + EN) * (X + EN))