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])
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)
def test_sparse_solver(self): print( '\nChecking homogenisation with low-rank tensor approximations...') tic = Timer('homogenisation') N = 5 for dim, material, kind in [(2, 0, 0), (2, 3, 1), (3, 1, 1), (3, 0, 2)]: print('dim={}, material={}, kind={}'.format(dim, material, kind)) pars, pars_sparse = get_default_parameters(dim, N, material, kind) pars_sparse.debug = True pars_sparse.solver.update(dict(rank=5, maxiter=10)) prt.disable() Aga, Agani, Agas, Aganis = get_material_coef( material, pars, pars_sparse) if material in [0, 3]: resP_Ga = homog_Ga_full_potential(Aga, pars) resS_Ga = homog_Ga_sparse(Agas, pars_sparse) if material in [1, 2, 4]: resP_GaNi = homog_GaNi_full_potential(Agani, Aga, pars) resS_GaNi = homog_GaNi_sparse(Aganis, Agas, pars_sparse) prt.enable() if material in [0, 3]: self.assertAlmostEqual(resP_Ga.Fu.mean(), 0) self.assertAlmostEqual(resS_Ga.Fu.mean(), 0) self.assertAlmostEqual(np.abs(resP_Ga.AH - resS_Ga.AH), 0, delta=1e-4) if material in [1, 2, 4]: self.assertAlmostEqual(resP_GaNi.Fu.mean(), 0) self.assertAlmostEqual(resS_GaNi.Fu.mean(), 0) self.assertAlmostEqual(np.abs(resP_GaNi.AH - resS_GaNi.AH), 0, delta=1e-4) tic.measure() print('...ok')
def calculate_AH_sparse(Agas, Aniso, FGX, method='full', rank=None, tol=None): tic = Timer(name='AH') AH = 0. if method in ['full']: Aga = Agas.full(multype=00) FGXf = [T.full() for T in FGX] for i in range(FGX.__len__()): AH += (Aga * FGXf[i]) * FGXf[i] for j in range(FGX.__len__()): AH += (Aniso[i, j] * FGXf[i]) * FGXf[j] elif method in ['tensorsLowRank']: assert (np.linalg.norm(Aniso) < 1e-12) for ii in range(FGX.__len__()): AH += (Agas * FGX[ii]).truncate(rank=rank, tol=tol).scal(FGX[ii]) else: raise NotImplementedError() tic.measure() return AH
def get_material_coef(material, pars, pars_sparse, ga=True): # get configuration settings pars, pars_sparse, mat_conf = getMat_conf(material, pars, pars_sparse) # generating material coefficients mat = Material(mat_conf) mats = LowRankMaterial(mat_conf, pars_sparse.kind) Agani = mat.get_A_GaNi(pars.N, primaldual='primal') Aganis = mats.get_A_GaNi(pars_sparse.N, primaldual='primal', k=pars_sparse.matrank) Agani.val = recover_Agani(Agani, Aganis) if ga: Aga = mat.get_A_Ga(pars.Nbar(pars.N), primaldual='primal') Agas = mats.get_A_Ga(pars_sparse.Nbar(pars_sparse.N), primaldual='primal', k=pars_sparse.matrank) Aga.val = recover_Aga(Aga, Agas) else: Aga = None Agas = None if 'Aniso' in mat_conf: # workaround for anisotropic material Aniso = mat_conf['Aniso'] Agani.add_mean(Aniso) if ga: Aga.add_mean(Aniso) pars_sparse.update(Struct(Aniso=Aniso)) tic = Timer('calc_eig') eigs = Agani.calc_eigs(symmetric=True) tic.measure() pars_sparse.solver['alpha'] = 0.5 * (eigs.min() + eigs.max()) else: pars_sparse.solver['alpha'] = 0.5 * (Agani[0, 0].min() + Agani[0, 0].max()) return Aga, Agani, Agas, Aganis
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)
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
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])