def matrix(self, shape=None): """ This function returns the object as a matrix of DFT or iDFT resp. """ N=self.N prodN=np.prod(N) if shape is not None: dim=np.prod(np.array(shape)) elif hasattr(self, 'shape'): dim=np.prod(np.array(shape)) else: raise ValueError('Missing shape of the DFT.') proddN=dim*prodN ZN_input=Grid.get_ZNl(N, fft_form=0) ZN_output=Grid.get_ZNl(N, fft_form='c') if self.inverse: DFTcoef=lambda k, l, N: np.exp(2*np.pi*1j*np.sum(k*l/N)) else: DFTcoef=lambda k, l, N: np.exp(-2*np.pi*1j*np.sum(k*l/N))/np.prod(N) DTM=np.zeros([self.pN(), self.pN()], dtype=np.complex128) for ii, kk in enumerate(itertools.product(*tuple(ZN_output))): for jj, ll in enumerate(itertools.product(*tuple(ZN_input))): DTM[ii, jj]=DFTcoef(np.array(kk, dtype=np.float), np.array(ll), N) DTMd=npmatlib.zeros([proddN, proddN], dtype=np.complex128) for ii in range(dim): DTMd[prodN*ii:prodN*(ii+1), prodN*ii:prodN*(ii+1)]=DTM return DTMd
def matrix(self, shape=None): """ This function returns the object as a matrix of DFT or iDFT resp. """ N = self.N prodN = np.prod(N) if shape is not None: dim = np.prod(np.array(shape)) elif hasattr(self, 'shape'): dim = np.prod(np.array(shape)) else: raise ValueError('Missing shape of the DFT.') proddN = dim * prodN ZN_input = Grid.get_ZNl(N, fft_form=0) ZN_output = Grid.get_ZNl(N, fft_form='c') if self.inverse: DFTcoef = lambda k, l, N: np.exp(2 * np.pi * 1j * np.sum(k * l / N) ) else: DFTcoef = lambda k, l, N: np.exp(-2 * np.pi * 1j * np.sum( k * l / N)) / np.prod(N) DTM = np.zeros([self.pN(), self.pN()], dtype=np.complex128) for ii, kk in enumerate(itertools.product(*tuple(ZN_output))): for jj, ll in enumerate(itertools.product(*tuple(ZN_input))): DTM[ii, jj] = DFTcoef(np.array(kk, dtype=np.float), np.array(ll), N) DTMd = npmatlib.zeros([proddN, proddN], dtype=np.complex128) for ii in range(dim): DTMd[prodN * ii:prodN * (ii + 1), prodN * ii:prodN * (ii + 1)] = DTM return DTMd
def div(X): if X.shape == (1, ): shape = () else: shape = X.shape[:-1] assert (X.shape[-1] == X.dim) assert (X.order == 1) dX = Tensor(shape=shape, N=X.N, Fourier=True, fft_form=X.fft_form) if X.Fourier: FX = X else: F = DFT(N=X.N, fft_form=X.fft_form) FX = F(X) dim = len(X.N) freq = Grid.get_freq(X.N, X.Y, fft_form=FX.fft_form) strfreq = 'xyz' coef = 2 * np.pi * 1j for ii in range(X.dim): mul_str = '{0},...{1}->...{1}'.format(strfreq[ii], strfreq[:dim]) dX.val += np.einsum(mul_str, coef * freq[ii], FX.val[ii], dtype=np.complex) if not X.Fourier: iF = DFT(N=X.N, inverse=True, fft_form=dX.fft_form) dX = iF(dX) dX.name = 'div({0})'.format(X.name[:10]) return dX
def get_weights_lin(h, Nbar, Y): """ it evaluates integral weights, which are used for upper-lower bounds calculation, with bilinear inclusion at rectangular area Parameters ---------- h - the parameter determining the size of inclusion (half-size of support) Nbar - no. of points of regular grid where the weights are evaluated Y - the size of periodic unit cell Returns ------- Wphi - integral weights at regular grid sizing Nbar """ d = np.size(Y) meas_puc = np.prod(Y) ZN2l = Grid.get_ZNl(Nbar, fft_form='c') Wphi = np.ones(Nbar) / meas_puc for ii in np.arange(d): Nshape = np.ones(d, dtype=np.int) Nshape[ii] = Nbar[ii] Nrep = np.copy(Nbar) Nrep[ii] = 1 Wphi *= h[ii] * np.tile( np.reshape((np.sinc(h[ii] * ZN2l[ii] / Y[ii]))**2, Nshape), Nrep) return Wphi
def get_weights_circ(r, Nbar, Y): """ it evaluates integral weights, which are used for upper-lower bounds calculation, with constant circular inclusion Parameters ---------- r - the parameter determining the size of inclusion Nbar - no. of points of regular grid where the weights are evaluated Y - the size of periodic unit cell Returns ------- Wphi - integral weights at regular grid sizing Nbar """ d = np.size(Y) ZN2l = Grid.get_ZNl(Nbar, fft_form='c') meas_puc = np.prod(Y) circ = 0 for m in range(d): Nshape = np.ones(d, dtype=np.int) Nshape[m] = Nbar[m] Nrep = np.copy(Nbar) Nrep[m] = 1 xi_p2 = np.tile(np.reshape((ZN2l[m] / Y[m])**2, Nshape), Nrep) circ += xi_p2 circ = circ**0.5 ind = mean_index(Nbar, fft_form='c') circ[ind] = 1. Wphi = r**2 * sp.jn(1, 2 * np.pi * circ * r) / (circ * r) Wphi[ind] = np.pi * r**2 Wphi = Wphi / meas_puc return Wphi
def scalar(N, Y, fft_form=fft_form_default): dim = np.size(N) N = np.array(N, dtype=np.int) xi = Grid.get_freq(N, Y, fft_form=fft_form) N_fft=tuple(xi[i].size for i in range(dim)) hGrad = np.zeros((dim,)+N_fft) # zero initialize for ind in itertools.product(*[range(n) for n in N_fft]): for i in range(dim): hGrad[i][ind] = xi[i][ind[i]] kok= np.einsum('i...,j...->ij...', hGrad, hGrad).real k2 = np.einsum('i...,i...', hGrad, hGrad).real ind_center=mean_index(N, fft_form=fft_form) k2[ind_center]=1. G0lval=np.zeros_like(kok) Ival=np.zeros_like(kok) for ii in range(dim): # diagonal components G0lval[ii, ii][ind_center] = 1 Ival[ii, ii] = 1 G1l=Tensor(name='G1', val=kok/k2, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form) G0l=Tensor(name='G1', val=G0lval, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form) I = Tensor(name='I', val=Ival, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form) G2l=I-G1l-G0l return G0l, G1l, G2l
def scalar(N, Y, fft_form=fft_form_default): dim = np.size(N) N = np.array(N, dtype=np.int) xi = Grid.get_freq(N, Y, fft_form=fft_form) N_fft=tuple(xi[i].size for i in range(dim)) hGrad = np.zeros((dim,)+N_fft) # zero initialize for ind in itertools.product(*[list(range(n)) for n in N_fft]): for i in range(dim): hGrad[i][ind] = xi[i][ind[i]] kok= np.einsum('i...,j...->ij...', hGrad, hGrad).real k2 = np.einsum('i...,i...', hGrad, hGrad).real ind_center=mean_index(N, fft_form=fft_form) k2[ind_center]=1. G0lval=np.zeros_like(kok) Ival=np.zeros_like(kok) for ii in range(dim): # diagonal components G0lval[ii, ii][ind_center] = 1 Ival[ii, ii] = 1 G1l=Tensor(name='G1', val=kok/k2, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form) G0l=Tensor(name='G1', val=G0lval, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form) I = Tensor(name='I', val=Ival, order=2, N=N, Y=Y, multype=21, Fourier=True, fft_form=fft_form) G2l=I-G1l-G0l return G0l, G1l, G2l
def get_weights_circ(r, Nbar, Y): """ it evaluates integral weights, which are used for upper-lower bounds calculation, with constant circular inclusion Parameters ---------- r - the parameter determining the size of inclusion Nbar - no. of points of regular grid where the weights are evaluated Y - the size of periodic unit cell Returns ------- Wphi - integral weights at regular grid sizing Nbar """ d = np.size(Y) ZN2l = Grid.get_ZNl(Nbar, fft_form='c') meas_puc = np.prod(Y) circ = 0 for m in range(d): Nshape = np.ones(d, dtype=np.int) Nshape[m] = Nbar[m] Nrep = np.copy(Nbar) Nrep[m] = 1 xi_p2 = np.tile(np.reshape((ZN2l[m]/Y[m])**2, Nshape), Nrep) circ += xi_p2 circ = circ**0.5 ind = mean_index(Nbar, fft_form='c') circ[ind] = 1. Wphi = r**2 * sp.jn(1, 2*np.pi*circ*r) / (circ*r) Wphi[ind] = np.pi*r**2 Wphi = Wphi / meas_puc return Wphi
def grad(X): if X.shape==(1,): shape=(X.dim,) else: shape=X.shape+(X.dim,) name='grad({0})'.format(X.name[:10]) gX=Tensor(name=name, shape=shape, N=X.N, Fourier=True, fft_form=X.fft_form) if X.Fourier: FX=X else: F=DFT(N=X.N, fft_form=X.fft_form) # TODO:change to X.fourier() FX=F(X) dim=len(X.N) freq=Grid.get_freq(X.N, X.Y, fft_form=X.fft_form) strfreq='xyz' coef=2*np.pi*1j val=np.empty((X.dim,)+X.shape+X.N_fft, dtype=np.complex) for ii in range(X.dim): mul_str='{0},...{1}->...{1}'.format(strfreq[ii], strfreq[:dim]) val[ii]=np.einsum(mul_str, coef*freq[ii], FX.val, dtype=np.complex) if X.shape==(1,): gX.val=np.squeeze(val) else: gX.val=np.moveaxis(val, 0, X.order) if not X.Fourier: iF=DFT(N=X.N, inverse=True, fft_form=gX.fft_form) gX=iF(gX) gX.name='grad({0})'.format(X.name[:10]) return gX
def div(X): if X.shape==(1,): shape=() else: shape=X.shape[:-1] assert(X.shape[-1]==X.dim) assert(X.order==1) dX=Tensor(shape=shape, N=X.N, Fourier=True, fft_form=X.fft_form) if X.Fourier: FX=X else: F=DFT(N=X.N, fft_form=X.fft_form) FX=F(X) dim=len(X.N) freq=Grid.get_freq(X.N, X.Y, fft_form=FX.fft_form) strfreq='xyz' coef=2*np.pi*1j for ii in range(X.dim): mul_str='{0},...{1}->...{1}'.format(strfreq[ii], strfreq[:dim]) dX.val+=np.einsum(mul_str, coef*freq[ii], FX.val[ii], dtype=np.complex) if not X.Fourier: iF=DFT(N=X.N, inverse=True, fft_form=dX.fft_form) dX=iF(dX) dX.name='div({0})'.format(X.name[:10]) return dX
def get_weights_lin(h, Nbar, Y): """ it evaluates integral weights, which are used for upper-lower bounds calculation, with bilinear inclusion at rectangular area Parameters ---------- h - the parameter determining the size of inclusion (half-size of support) Nbar - no. of points of regular grid where the weights are evaluated Y - the size of periodic unit cell Returns ------- Wphi - integral weights at regular grid sizing Nbar """ d = np.size(Y) meas_puc = np.prod(Y) ZN2l = Grid.get_ZNl(Nbar, fft_form='c') Wphi = np.ones(Nbar) / meas_puc for ii in np.arange(d): Nshape = np.ones(d, dtype=np.int) Nshape[ii] = Nbar[ii] Nrep = np.copy(Nbar) Nrep[ii] = 1 Wphi *= h[ii]*np.tile(np.reshape((np.sinc(h[ii]*ZN2l[ii]/Y[ii]))**2, Nshape), Nrep) return Wphi
def get_A_GaNi(self, N, primaldual='primal', tensor=True): """ Returns stiffness matrix for a scheme with trapezoidal quadrature rule. """ coord = Grid.get_coordinates(N, self.Y) A = self.evaluate(coord, tensor=tensor) if primaldual is 'dual': A = A.inv() return A.shift()
def potential(X, small_strain=False): if X.Fourier: FX = X else: F = DFT(N=X.N, fft_form=X.fft_form) FX = F(X) freq = Grid.get_freq(X.N, X.Y, fft_form=FX.fft_form) if X.order == 1: assert (X.dim == X.shape[0]) iX = Tensor(name='potential({0})'.format(X.name[:10]), shape=(1, ), N=X.N, Fourier=True, fft_form=FX.fft_form) iX.val[0] = potential_scalar(FX.val, freq=freq, mean_index=FX.mean_index()) elif X.order == 2: assert (X.dim == X.shape[0]) assert (X.dim == X.shape[1]) iX = Tensor(name='potential({0})'.format(X.name[:10]), shape=(X.dim, ), N=X.N, Fourier=True, fft_form=FX.fft_form) if not small_strain: for ii in range(X.dim): iX.val[ii] = potential_scalar(FX.val[ii], freq=freq, mean_index=FX.mean_index()) else: assert ((X - X.transpose()).norm() < 1e-14) # symmetricity omeg = FX.zeros_like() # non-symmetric part of the gradient gomeg = Tensor(name='potential({0})'.format(X.name[:10]), shape=FX.shape + (X.dim, ), N=X.N, Fourier=True) grad_ep = grad(FX) # gradient of strain gomeg.val = np.einsum('ikj...->ijk...', grad_ep.val) - np.einsum( 'jki...->ijk...', grad_ep.val) for ij in itertools.product(list(range(X.dim)), repeat=2): omeg.val[ij] = potential_scalar(gomeg.val[ij], freq=freq, mean_index=FX.mean_index()) gradu = FX + omeg iX = potential(gradu, small_strain=False) if X.Fourier: return iX else: iF = DFT(N=X.N, inverse=True, fft_form=FX.fft_form) return iF(iX)
def savefig(self, fname='material.pdf', N=50 * np.ones(2)): import pylab as pl pl.figure(num=None, figsize=(3, 3), dpi=1000) coord = Grid.get_coordinates(N, self.Y) vals = self.evaluate(coord)[0, 0] pl.pcolor(coord[0], coord[1], -vals) pl.xlim([-self.Y[0] / 2, self.Y[0] / 2]) pl.ylim([-self.Y[1] / 2, self.Y[1] / 2]) pl.xlabel(r'coordinate $x_1$') pl.ylabel(r'coordinate $x_2$') pl.savefig(fname, pad_inches=0.02, bbox_inches='tight') pl.close()
def savefig(self, fname='material.pdf', N=50*np.ones(2)): import pylab as pl pl.figure(num=None, figsize=(3,3), dpi=1000) coord = Grid.get_coordinates(N, self.Y) vals = self.evaluate(coord)[0, 0] pl.pcolor(coord[0], coord[1], -vals) pl.xlim([-self.Y[0]/2, self.Y[0]/2]) pl.ylim([-self.Y[1]/2, self.Y[1]/2]) pl.xlabel(r'coordinate $x_1$') pl.ylabel(r'coordinate $x_2$') pl.savefig(fname, pad_inches=0.02, bbox_inches='tight') pl.close()
def get_shift_inclusion(N, h, Y): N = np.array(N, dtype=np.int) Y = np.array(Y, dtype=np.float) dim = N.size ZN = Grid.get_ZNl(N) SS = np.ones(N, dtype=np.complex128) for ii in np.arange(dim): Nshape = np.ones(dim, dtype=np.int) Nshape[ii] = N[ii] Nrep = N Nrep[ii] = 1 SS *= np.tile(np.reshape(np.exp(-2*np.pi*1j*(h[ii]*ZN[ii]/Y[ii])), Nshape), Nrep) return SS
def get_shift_inclusion(N, h, Y): N = np.array(N, dtype=np.int) Y = np.array(Y, dtype=np.float) dim = N.size ZN = Grid.get_ZNl(N) SS = np.ones(N, dtype=np.complex128) for ii in np.arange(dim): Nshape = np.ones(dim, dtype=np.int) Nshape[ii] = N[ii] Nrep = N Nrep[ii] = 1 SS *= np.tile( np.reshape(np.exp(-2 * np.pi * 1j * (h[ii] * ZN[ii] / Y[ii])), Nshape), Nrep) return SS
def grad_tensor(N, Y=None, fft_form=fft_form_default): if Y is None: Y = np.ones_like(N) # scalar valued versions of gradient and divergence N = np.array(N, dtype=np.int) dim = N.size freq = Grid.get_xil(N, Y, fft_form=fft_form) N_fft=tuple(freq[i].size for i in range(dim)) hGrad = np.zeros((dim,)+ N_fft) # zero initialize for ind in itertools.product(*[range(n) for n in N_fft]): for i in range(dim): hGrad[i][ind] = freq[i][ind[i]] hGrad = hGrad*2*np.pi*1j return Tensor(name='hgrad', val=hGrad, order=1, N=N, multype='grad', Fourier=True, fft_form=fft_form)
def grad_tensor(N, Y=None, fft_form=fft_form_default): if Y is None: Y = np.ones_like(N) # scalar valued versions of gradient and divergence N = np.array(N, dtype=np.int) dim = N.size freq = Grid.get_xil(N, Y, fft_form=fft_form) N_fft=tuple(freq[i].size for i in range(dim)) hGrad = np.zeros((dim,)+ N_fft) # zero initialize for ind in itertools.product(*[list(range(n)) for n in N_fft]): for i in range(dim): hGrad[i][ind] = freq[i][ind[i]] hGrad = hGrad*2*np.pi*1j return Tensor(name='hgrad', val=hGrad, order=1, N=N, multype='grad', Fourier=True, fft_form=fft_form)
def curl_norm(e, Y): """ it calculates curl-based norm, it controls that the fields are curl-free with zero mean as it is required of electric fields Parameters ---------- e - electric field Y - the size of periodic unit cell Returns ------- curlnorm - curl-based norm """ N=np.array(np.shape(e[0])) d=np.size(N) xil=Grid.get_xil(N, Y) xiM=[] Fe=[] for m in np.arange(d): Nshape=np.ones(d) Nshape[m]=N[m] Nrep=np.copy(N) Nrep[m]=1 xiM.append(np.tile(np.reshape(xil[m], Nshape), Nrep)) Fe.append(DFT.fftnc(e[m], N)/np.prod(N)) if d==2: Fe.append(np.zeros(N)) xiM.append(np.zeros(N)) ind_mean=tuple(np.fix(N/2)) curl=[] e0=[] for m in np.arange(3): j=(m+1)%3 k=(j+1)%3 curl.append(xiM[j]*Fe[k]-xiM[k]*Fe[j]) e0.append(np.real(Fe[m][ind_mean])) curl=np.array(curl) curlnorm=np.real(np.sum(curl[:]*np.conj(curl[:]))) curlnorm=(curlnorm/np.prod(N))**0.5 norm_e0=np.linalg.norm(e0) if norm_e0>1e-10: curlnorm=curlnorm/norm_e0 return curlnorm
def elasticity_large_deformation(N, Y, fft_form=fft_form_default): N = np.array(N, dtype=np.int) dim = N.size assert(dim==3) freq = Grid.get_freq(N, Y, fft_form=fft_form) N_fft=tuple(freq[i].size for i in range(dim)) Ghat = np.zeros(np.hstack([dim*np.ones(4, dtype=np.int), N_fft])) delta = lambda i,j: np.float(i==j) for i, j, k, l in itertools.product(list(range(dim)), repeat=4): for x, y, z in np.ndindex(*N_fft): q = np.array([freq[0][x], freq[1][y], freq[2][z]]) if not q.dot(q) == 0: Ghat[i,j,k,l,x,y,z] = delta(i,k)*q[j]*q[l] / (q.dot(q)) Ghat_tensor = Tensor(name='Ghat', val=Ghat, order=4, N=N, multype=42, Fourier=True, fft_form=fft_form) return Ghat_tensor
def elasticity_large_deformation(N, Y, fft_form=fft_form_default): N = np.array(N, dtype=np.int) dim = N.size assert(dim==3) freq = Grid.get_freq(N, Y, fft_form=fft_form) N_fft=tuple(freq[i].size for i in range(dim)) Ghat = np.zeros(np.hstack([dim*np.ones(4, dtype=np.int), N_fft])) delta = lambda i,j: np.float(i==j) for i, j, k, l in itertools.product(range(dim), repeat=4): for x, y, z in np.ndindex(*N_fft): q = np.array([freq[0][x], freq[1][y], freq[2][z]]) if not q.dot(q) == 0: Ghat[i,j,k,l,x,y,z] = delta(i,k)*q[j]*q[l] / (q.dot(q)) Ghat_tensor = Tensor(name='Ghat', val=Ghat, order=4, N=N, multype=42, Fourier=True, fft_form=fft_form) return Ghat_tensor
def plot(self, ind=slice(None), N=None, filen=None, ptype='imshow'): if N is None: N = self.N from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt from ffthompy.trigpol import Grid coord = Grid.get_coordinates(N, self.Y) Z = self.project(N) Z = Z.val[ind] if self.Fourier: Z = np.abs(Z) if Z.ndim != 2: raise ValueError("The plotting is suited only for dim=2!") fig = plt.figure() if ptype in ['wireframe']: ax = fig.add_subplot(111, projection='3d') ax.plot_wireframe(coord[-2], coord[-1], Z) elif ptype in ['surface']: from matplotlib import cm ax = fig.gca(projection='3d') surf = ax.plot_surface(coord[-2], coord[-1], Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False) fig.colorbar(surf, shrink=0.5, aspect=5) elif ptype in ['imshow']: ax = plt.imshow(Z) plt.colorbar(ax) if filen is None: plt.show() else: plt.savefig(filen)
def potential(X, small_strain=False): if X.Fourier: FX=X else: F=DFT(N=X.N, fft_form=X.fft_form) FX=F(X) freq=Grid.get_freq(X.N, X.Y, fft_form=FX.fft_form) if X.order==1: assert(X.dim==X.shape[0]) iX=Tensor(name='potential({0})'.format(X.name[:10]), shape=(1,), N=X.N, Fourier=True, fft_form=FX.fft_form) iX.val[0]=potential_scalar(FX.val, freq=freq, mean_index=FX.mean_index()) elif X.order==2: assert(X.dim==X.shape[0]) assert(X.dim==X.shape[1]) iX=Tensor(name='potential({0})'.format(X.name[:10]), shape=(X.dim,), N=X.N, Fourier=True, fft_form=FX.fft_form) if not small_strain: for ii in range(X.dim): iX.val[ii]=potential_scalar(FX.val[ii], freq=freq, mean_index=FX.mean_index()) else: assert((X-X.transpose()).norm()<1e-14) # symmetricity omeg=FX.zeros_like() # non-symmetric part of the gradient gomeg=Tensor(name='potential({0})'.format(X.name[:10]), shape=FX.shape+(X.dim,), N=X.N, Fourier=True) grad_ep=grad(FX) # gradient of strain gomeg.val=np.einsum('ikj...->ijk...', grad_ep.val)-np.einsum('jki...->ijk...', grad_ep.val) for ij in itertools.product(range(X.dim), repeat=2): omeg.val[ij]=potential_scalar(gomeg.val[ij], freq=freq, mean_index=FX.mean_index()) gradu=FX+omeg iX=potential(gradu, small_strain=False) if X.Fourier: return iX else: iF=DFT(N=X.N, inverse=True, fft_form=FX.fft_form) return iF(iX)
def plot(self, ind=slice(None), N=None, filen=None, ptype='imshow'): assert(not self.Fourier) if N is None: N = self.N from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt from ffthompy.trigpol import Grid coord=Grid.get_coordinates(N, self.Y) Z=self.project(N) Z = Z.val[ind] if Z.ndim != 2: raise ValueError("The plotting is suited only for dim=2!") fig = plt.figure() if ptype in ['wireframe']: ax = fig.add_subplot(111, projection='3d') ax.plot_wireframe(coord[-2], coord[-1], Z) elif ptype in ['surface']: from matplotlib import cm ax = fig.gca(projection='3d') surf = ax.plot_surface(coord[-2], coord[-1], Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False) fig.colorbar(surf, shrink=0.5, aspect=5) elif ptype in ['imshow']: ax = plt.imshow(Z) plt.colorbar(ax) if filen is None: plt.show() else: plt.savefig(filen)
def plot(self, ind=0, N=None, filen=None, Y=None, ptype='surface'): dim=self.N.size if dim!=2: raise ValueError("The plotting is suited only for dim=2!") if Y is None: Y=np.ones(dim) if N is None: N=self.N from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt from ffthompy.trigpol import Grid fig=plt.figure() coord=Grid.get_coordinates(N, Y) if np.all(np.greater(N, self.N)): Z=DFT.ifftnc(enlarge(DFT.fftnc(self.val[ind], self.N), N), N).real elif np.all(np.less(N, self.N)): Z=DFT.ifftnc(decrease(DFT.fftnc(self.val[ind], self.N), N), N).real elif np.allclose(N, self.N): Z=self.val[ind] if ptype in ['wireframe']: ax=fig.add_subplot(111, projection='3d') ax.plot_wireframe(coord[0], coord[1], Z) elif ptype in ['surface']: from matplotlib import cm ax=fig.gca(projection='3d') surf=ax.plot_surface(coord[0], coord[1], Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False) fig.colorbar(surf, shrink=0.5, aspect=5) if filen is None: plt.show() else: plt.savefig(filen)
def matrix(self): """ This function returns the object as a matrix of DFT or iDFT resp. """ N=self.N prodN=np.prod(N) proddN=self.d*prodN ZNl=Grid.get_ZNl(N, fft_form='c') if self.inverse: DFTcoef=lambda k, l, N: np.exp(2*np.pi*1j*np.sum(k*l/N)) else: DFTcoef=lambda k, l, N: np.exp(-2*np.pi*1j*np.sum(k*l/N))/np.prod(N) DTM=np.zeros([self.pN(), self.pN()], dtype=np.complex128) for ii, kk in enumerate(itertools.product(*tuple(ZNl))): for jj, ll in enumerate(itertools.product(*tuple(ZNl))): DTM[ii, jj]=DFTcoef(np.array(kk, dtype=np.float), np.array(ll), N) DTMd=npmatlib.zeros([proddN, proddN], dtype=np.complex128) for ii in range(self.d): DTMd[prodN*ii:prodN*(ii+1), prodN*ii:prodN*(ii+1)]=DTM return DTMd
def grad_tensor(N, Y, kind='TensorTrain'): assert(kind.lower() in ['cano','canotensor','tucker','tt','tensortrain']) dim=Y.size freq=Grid.get_xil(N, Y, fft_form='c') hGrad_s=[] for ii in range(dim): basis=[] for jj in range(dim): if ii==jj: basis.append(np.atleast_2d(freq[jj]*2*np.pi*1j)) else: basis.append(np.atleast_2d(np.ones(N[jj]))) if kind.lower() in ['cano', 'canotensor','tucker']: hGrad_s.append(SparseTensor(kind=kind, name='hGrad({})'.format(ii), core=np.array([1.]), basis=basis, Fourier=True, fft_form='c').set_fft_form()) elif kind.lower() in ['tt','tensortrain']: cl = [bas.reshape((1,-1,1)) for bas in basis] hGrad_s.append(SparseTensor(kind=kind, core=cl, name='hGrad({})'.format(ii), Fourier=True, fft_form='c').set_fft_form()) return hGrad_s
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()
phi_fine = phi.project(M) print(phi_fine) print( """The procedure is provided by VecTri.enlarge(M) function, which consists of a calculation of Fourier coefficients, putting zeros to Fourier coefficients with high frequencies, and inverse FFT that evaluates the polynomial on a fine grid. """) print("""In order to plot this polynomial, we also set a size of a cell Y =""") Y = np.ones(d) # size of a cell print(Y) print(""" and evaluate the coordinates of grid points, which are stored in numpy.ndarray of following shape: coord.shape =""") coord = Grid.get_coordinates(M, Y) print(coord.shape) if __name__ == "__main__": print(""" Now, the plot of fundamental trigonometric polynomial is shown:""") from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot_wireframe(coord[0], coord[1], phi_fine.val) plt.show() print('END')
phi_fine = phi.project(M) print(phi_fine) print("""The procedure is provided by VecTri.enlarge(M) function, which consists of a calculation of Fourier coefficients, putting zeros to Fourier coefficients with high frequencies, and inverse FFT that evaluates the polynomial on a fine grid. """) print("""In order to plot this polynomial, we also set a size of a cell Y =""") Y = np.ones(d) # size of a cell print(Y) print(""" and evaluate the coordinates of grid points, which are stored in numpy.ndarray of following shape: coord.shape =""") coord = Grid.get_coordinates(M, Y) print(coord.shape) if __name__ == "__main__": print(""" Now, the plot of fundamental trigonometric polynomial is shown:""") from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot_wireframe(coord[0], coord[1], phi_fine.val) plt.show() print('END')
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(*(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) / 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()
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
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
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
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