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')
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')
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 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 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, centered=True, 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 = LinOper(name='G1', mat=[[FiN, hG1hN + hG1sN, FN]]) G2N = LinOper(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 = LinOper(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 = VecTri(name='EN', macroval=E, N=Nbar, Fourier=False) # initial approximation for solvers x0 = VecTri(N=Nbar, d=D, Fourier=False) 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)
# projections in Fourier space _, hG1N, _ = proj.scalar(pb['solve']['N'], pb['material']['Y'], centered=True, NyqNul=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 = LinOper(name='G1', mat=[[FiN, hG1N, FN]]) # projection in original space Afun = LinOper(name='FiGFA', mat=[[G1N, A]]) # lin. operator for a linear system E = np.zeros(dim); E[0] = 1 # macroscopic load EN = VecTri(name='EN', macroval=E, N=Nbar, Fourier=False) # constant trig. pol. x0 = VecTri(N=Nbar, d=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')
# initial approximation to solvers x0 = Tensor(N=N, shape=(D, ), Fourier=False) B = Afun(-EN) # RHS B_MS = Afun_MS(-EN) # RHS print(""" The linear system is solved with different algorithms:""") print(""" version #1 : The solution by Conjugate gradients with zero initial vector; the macroscopic value occurs on right-hand-side as a load.""") from ffthompy.general.solver import linear_solver X, info = linear_solver(solver='CG', Afun=Afun, B=B, x0=x0, par=pb['solver'], callback=None) print('Homogenised properties (component 11) = {0}'.format( A(X + EN) * (X + EN))) print(""" version #2 : The solution by Conjugate gradients with initial vector corresponding to macroscopic value; in this case, the right-hand-side remains zero. The difference to previous solution is printed: (X+EN == X2) =""") X2, info2 = linear_solver(solver='CG', Afun=Afun, B=x0,
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)
Afun = Operator(name='FiGFA', mat=[[G1N, A]]) # initial approximation to solvers x0 = Tensor(N=N, shape=(D,), Fourier=False) B = Afun(-EN) # RHS B_MS = Afun_MS(-EN) # RHS print(""" The linear system is solved with different algorithms:""") print(""" version #1 : The solution by Conjugate gradients with zero initial vector; the macroscopic value occurs on right-hand-side as a load.""") from ffthompy.general.solver import linear_solver X, info = linear_solver(solver='CG', Afun=Afun, B=B, x0=x0, par=pb['solver'], callback=None) print('Homogenised properties (component 11) = {0}'.format(A(X+EN)*(X+EN))) print(""" version #2 : The solution by Conjugate gradients with initial vector corresponding to macroscopic value; in this case, the right-hand-side remains zero. The difference to previous solution is printed: (X+EN == X2) =""") X2, info2 = linear_solver(solver='CG', Afun=Afun, B=x0, x0=EN, par=pb['solver'], callback=None) print(X+EN == X2) print(""" version #3 :
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')