Example #1
0
    def test_mean(self):
        print('\nChecking method mean() ...')
        a = SparseTensor(kind='cano', val=self.T2d)
        self.assertAlmostEqual(np.mean(self.T2d), a.mean())
        self.assertAlmostEqual(np.mean(self.T2d), a.fourier().mean())

        a = SparseTensor(kind='tucker', val=self.T3d)
        self.assertAlmostEqual(np.mean(self.T3d), a.mean())
        self.assertAlmostEqual(np.mean(self.T3d), a.fourier().mean())

        a = SparseTensor(kind='tt', val=self.T3d)
        self.assertAlmostEqual(np.mean(self.T3d), a.mean())
        self.assertAlmostEqual(np.mean(self.T3d), a.fourier().mean())
        print('...ok')
Example #2
0
def minimal_residual(Afun, B, x0=None, par=None):
    fast = par.get('fast')

    res = {'norm_res': [], 'kit': 0}
    if x0 is None:
        x = B * (1. / par['alpha'])
    else:
        x = x0
    x_sol = x  # solution with minimal residuum

    if 'norm' not in par:
        norm = lambda X: X.norm(normal_domain=False)

    residuum = B - Afun(x)
    res['norm_res'].append(norm(residuum))
    beta = Afun(residuum.truncate(tol=par['tol_truncate'], fast=fast))

    M = SparseTensor(kind=x.kind, val=np.ones(x.N.size * [
        3,
    ]), rank=1)  # constant field
    FM = M.fourier().enlarge(x.N)
    minres_fail_counter = 0

    while (res['norm_res'][-1] > par['tol'] and res['kit'] < par['maxiter']):
        res['kit'] += 1

        if par['approx_omega']:
            omega = res['norm_res'][-1] / norm(beta)  # approximate omega
        else:
            omega = beta.inner(residuum) / norm(beta)**2  # exact formula

        x = (x + residuum * omega)

        # setting correct mean
        x = (-FM * x.mean() + x).truncate(rank=par['rank'],
                                          tol=par['tol_truncate'],
                                          fast=fast)

        residuum = B - Afun(x)

        res['norm_res'].append(norm(residuum))

        if res['norm_res'][-1] <= np.min(res['norm_res'][:-1]):
            x_sol = x
        else:
            minres_fail_counter += 1
            if minres_fail_counter >= par['minres_fails']:
                print(
                    'Residuum has risen up {} times -> ending solver.'.format(
                        par['minres_fails']))
                break

        beta = Afun(
            residuum.truncate(tol=min([res['norm_res'][-1] / 1e1, par['tol']]),
                              fast=fast))

    return x_sol, res
Example #3
0
    def test_Fourier_truncation(self):
        print('\nChecking TT truncation in Fourier domain ...')
        N = np.random.randint(20, 50, size=3)
        a = np.arange(1, np.prod(N) + 1).reshape(N)
        cases = [[None] * 2, [None] * 2]
        # first a random test case
        cases[0] = [np.random.random(N), np.random.random(N)]
        # this produces a "smooth", more realistic, tensor with modest rank
        cases[1] = [np.sin(a) / a, np.exp(np.sin(a) / a)]

        for i in range(len(cases)):
            for fft_form in [0, 'c', 'sr']:

                a = cases[i][0]
                b = cases[i][1]
                ta = SparseTensor(
                    kind='tt', val=a, fft_form=fft_form
                )  # Fourier truncation works the best with option 'sr'
                tb = SparseTensor(kind='tt', val=b, fft_form=fft_form)
                tc = ta + tb
                k = tc.r[1:-1].max() / 2 - 5

                tct = tc.truncate(rank=k)

                err_normal_truncate = (tct - tc).norm()
                #                print("loss in normal  domain truncation:",norm(tct.full().val-(a+b) ))

                taf = ta.fourier()
                tbf = tb.fourier()
                tcf = taf + tbf
                tcft = tcf.truncate(rank=k)
                tcfti = tcft.fourier()
                #                print("norm of imag part of F inverse tensor",norm(tcfti.full().val.imag))

                err_Fourier_truncate = (tcfti - tc).norm()
                #                print("loss in Fourier domain truncation:",norm(tcfti.full().val-(a+b) ))

                # assert the two truncation errors are in the same order
                self.assertAlmostEqual(err_normal_truncate,
                                       err_Fourier_truncate,
                                       delta=err_normal_truncate * 3)

        print('...ok')
Example #4
0
def richardson(Afun, B, x0=None, rank=None, tol=None, par=None, norm=None):
    if isinstance(par['alpha'], float):
        omega = 1. / par['alpha']
    else:
        raise ValueError()
    res = {'norm_res': [], 'kit': 0}
    if x0 is None:
        x = B * omega
    else:
        x = x0

    if norm is None:
        norm = lambda X: X.norm()

    res['norm_res'].append(norm(B))

    M = SparseTensor(kind=x.kind, val=np.ones(x.N.size * [
        3,
    ]), rank=1)  # constant field
    FM = M.fourier().enlarge(x.N)

    norm_res = 1e15
    while (norm_res > par['tol'] and res['kit'] < par['maxiter']):
        res['kit'] += 1
        residuum = B - Afun(x)
        norm_res = norm(residuum)
        if par['divcrit'] and norm_res > res['norm_res'][res['kit'] - 1]:
            break

        x = (x + residuum * omega)
        x = (-FM * x.mean() + x).truncate(rank=rank, tol=tol,
                                          fast=True)  # setting correct mean

        res['norm_res'].append(norm_res)

    return x, res
Example #5
0
def cheby2TERM(Afun, B, x0=None, par={}, callback=None):
    """
    Chebyshev two-term iterative solver

    Parameters
    ----------
    Afun : a function, represnting linear function A in the system Ax =B
    B : tensorsLowRank tensor representing vector B in the right-hand side of linear system
    x0 : tensorsLowRank tensor representing initial approximation of solution of linear system
    par : dict
          parameters of the method
    callback :

    Returns
    -------
    x : resulting unknown vector
    res : dict
        results
    """

    if 'tol' not in par:
        par['tol'] = 1e-06
    if 'maxiter' not in par:
        par['maxiter'] = 1e7
    if 'eigrange' not in par:
        raise NotImplementedError("It is necessary to calculate eigenvalues.")
    else:
        Egv = par['eigrange']

    res = {'norm_res': [], 'kit': 0}

    bnrm2 = B.norm()
    Ib = 1.0 / bnrm2
    if bnrm2 == 0:
        bnrm2 = 1.0

    if x0 is None:
        x = B
    else:
        x = x0

    r = B - Afun(x)
    r0 = r.norm()
    res['norm_res'].append(Ib * r0)  # For Normal Residue

    if res['norm_res'][-1] < par['tol']:  # if errnorm is less than tol
        return x, res

    M = SparseTensor(kind=x.kind, val=np.ones(x.N.size * [
        3,
    ]), rank=1)  # constant field
    FM = M.fourier().enlarge(x.N)

    d = (Egv[1] + Egv[0]) / 2.0  # np.mean(par['eigrange'])
    c = (Egv[1] - Egv[0]) / 2.0  # par['eigrange'][1] - d
    v = x * 0.0
    while (res['norm_res'][-1] > par['tol']) and (res['kit'] < par['maxiter']):
        res['kit'] += 1
        x_prev = x
        if res['kit'] == 1:
            p = 0
            w = 1 / d
        elif res['kit'] == 2:
            p = -(1 / 2) * (c / d) * (c / d)
            w = 1 / (d - c * c / 2 / d)
        else:
            p = -(c * c / 4) * w * w
            w = 1 / (d - c * c * w / 4)
        v = (r - p * v).truncate(rank=par['rank'], tol=par['tol_truncate'])
        x = (x_prev + w * v)
        x = (-FM * x.mean() + x).truncate(
            rank=par['tol'], tol=par['tol_truncate'])  # setting correct mean
        r = B - Afun(x)

        res['norm_res'].append((1.0 / r0) * r.norm())

        if callback is not None:
            callback(x)

    if par['tol'] < res['norm_res']:  # if tolerance is less than error norm
        print("Chebyshev solver does not converges!")
    else:
        print("Chebyshev solver converges.")

    if res['kit'] == 0:
        res['norm_res'] = 0
    return x, res
Example #6
0
def minimal_residual_debug(Afun, B, x0=None, par=None):
    fast = par.get('fast')

    M = SparseTensor(kind=B.kind, val=np.ones(B.N.size * [
        3,
    ]), rank=1)  # constant field
    FM = M.fourier().enlarge(B.N)

    res = {'norm_res': [], 'kit': 0}
    if x0 is None:
        x = B * (1. / par['alpha'])
    else:
        x = x0

    if 'norm' not in par:
        norm = lambda X: X.norm(normal_domain=False)

    residuum = (B - Afun(x)).truncate(rank=None, tol=par['tol'], fast=fast)
    res['norm_res'].append(norm(residuum))
    beta = Afun(residuum)

    norm_res = res['norm_res'][res['kit']]

    while (norm_res > par['tol'] and res['kit'] < par['maxiter']):
        res['kit'] += 1
        print('iteration = {}'.format(res['kit']))

        if par['approx_omega']:
            omega = norm_res / norm(beta)  # approximate omega
        else:
            omega = beta.inner(residuum) / norm(beta)**2  # exact formula

        x = (x + residuum * omega)
        x = (-FM * x.mean() + x).truncate(
            rank=par['rank'], tol=par['tol'])  # setting correct mean

        tic = Timer('compute residuum')
        residuum = (B - Afun(x))
        #         residuum=residuum.truncate(rank=2*rank, tol=tol)
        #         residuum=(B-Afun(x)).truncate(rank=rank, tol=tol)
        #         residuum=(B-Afun(x))
        tic.measure()
        tic = Timer('residuum norm')
        norm_res = norm(residuum)
        tic.measure()
        if par['divcrit'] and norm_res > res['norm_res'][-1]:
            break
        res['norm_res'].append(norm_res)

        tic = Timer('truncate residuum')
        #         residuum_for_beta=residuum.truncate(rank=rank, tol=tol)
        #         residuum_for_beta=residuum.truncate(rank=None, tol=1-4)
        tol = min([norm_res / 1e1, par['tol']])
        residuum_for_beta = residuum.truncate(rank=None, tol=tol, fast=fast)
        tic.measure()
        print('tolerance={}, rank={}'.format(tol, residuum_for_beta.r))
        print('residuum_for_beta.r={}'.format(residuum_for_beta.r))
        tic = Timer('compute beta')
        beta = Afun(residuum_for_beta)
        tic.measure()
        pass
    return x, res
Example #7
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')
Example #8
0
def homog_GaNi_sparse(Aganis, Agas, pars):
    debug = getattr(pars, 'debug', False)

    N = Aganis.N
    dim = N.__len__()
    hGrad_s = sgrad_tensor(N, pars.Y, kind=pars.kind)

    Aniso = getattr(pars, 'Aniso', np.zeros([dim, dim]))

    # creating constant field in tensorsLowRank tensor
    Es = SparseTensor(name='E',
                      kind=pars.kind,
                      val=np.ones(dim * (3, )),
                      rank=1)
    Es = Es.fourier().enlarge(N).fourier()

    material_law = Material_law(Aganis, Aniso, Es)

    def DFAFGfun_s(X, rank=None, tol=None, fast=False):  # linear operator
        assert (X.Fourier)
        FGX = [(hGrad_s[ii] * X).fourier() for ii in range(dim)]
        AFGFx = material_law(FGX, rank=rank, tol=tol, fast=fast)
        # or in following: Fourier, reduce, truncate
        FAFGFx = [AFGFx[ii].fourier() for ii in range(dim)]
        GFAFGFx = hGrad_s[0] * FAFGFx[0]  # div
        for ii in range(1, dim):
            GFAFGFx += hGrad_s[ii] * FAFGFx[ii]
        GFAFGFx = GFAFGFx.truncate(rank=rank, tol=tol, fast=fast)
        GFAFGFx.name = 'fun(x)'
        return -GFAFGFx

    # R.H.S.
    Bs = hGrad_s[0] * (Aganis * Es).fourier()  # minus from B and from div
    Ps = get_preconditioner_sparse(N, pars)

    def PDFAFGfun_s(Fx,
                    rank=pars.solver['rank'],
                    tol=pars.solver['tol_truncate'],
                    fast=pars.solver['fast']):
        R = DFAFGfun_s(Fx, rank=rank, tol=tol, fast=fast)
        R = Ps * R
        R = R.truncate(rank=rank, tol=tol, fast=fast)
        return R

    PBs = Ps * Bs
    PBs2 = PBs.truncate(tol=pars.rhs_tol, fast=False)
    if debug:
        print('r.h.s. norm = {}; error={}; rank={}'.format(
            np.linalg.norm(PBs.full().val),
            np.linalg.norm(PBs.full().val - PBs2.full().val), PBs2.r))

    PBs = PBs2

    tic = Timer(name=pars.solver['method'])
    Fu, ress = linear_solver_lowrank(pars.solver['method'],
                                     Afun=PDFAFGfun_s,
                                     B=PBs,
                                     par=pars.solver)
    tic.measure()

    print('iterations of solver={}'.format(ress['kit']))
    print('norm of residuum={}'.format(ress['norm_res'][-1]))
    Fu.name = 'Fu'
    print('norm(resP)={}'.format(np.linalg.norm(
        (PBs - PDFAFGfun_s(Fu)).full())))

    if Agas is None:  # GaNi homogenised properties
        print('!!!!! homogenised properties are GaNi only !!!!!')
        FGX = [(hGrad_s[ii] * Fu).fourier() for ii in range(dim)]
        FGX[0] += Es  # adding mean
        AH = calculate_AH_sparse(Aganis, Aniso, FGX, method='full')
    else:
        Nbar = 2 * np.array(N) - 1
        FGX = [((hGrad_s[ii] * Fu).enlarge(Nbar)).fourier()
               for ii in range(dim)]
        Es = SparseTensor(kind=pars.kind, val=np.ones(Nbar), rank=1)
        FGX[0] += Es  # adding mean
        AH = calculate_AH_sparse(Agas, Aniso, FGX, method='full')

    return Struct(AH=AH, e=FGX, solver=ress, Fu=Fu, time=tic.vals[0][0])