def get_A_Ga(self, Nbar, primaldual='primal', order=None, P=None): """ Returns stiffness matrix for scheme with exact integration.""" if order is None and 'order' in self.conf: order = self.conf['order'] if order is None: 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]) return Matrix(name='A_Ga', val=val, Fourier=False) else: if P is None and 'P' in self.conf: P = self.conf['P'] coord = Grid.get_coordinates(P, self.Y) vals = self.evaluate(coord) dim = vals.d 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) Aapp = np.zeros(np.hstack([dim, dim, Nbar])) for m in np.arange(dim): for n in np.arange(dim): hAM0 = DFT.fftnc(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*factor-1) hAM = decrease(hAM0per, Nbar) else: raise ValueError() pNbar = np.prod(Nbar) """ if DFT is normalized in accordance with articles there should be np.prod(M) instead of np.prod(Nbar)""" Aapp[m, n] = np.real(pNbar*DFT.ifftnc(Wraw*hAM, Nbar)) name = 'A_Ga_o%d_P%d' % (order, P.max()) return Matrix(name=name, val=Aapp, Fourier=False)
def get_topologies(self, coord): """ Returns topologies at coordinates (coord). By a topology, it is understood a characteristic function (ones and zeros at coord) of individual inclusions (square, circle, etc.) usually defined in input file. """ inclusions = self.conf['inclusions'] params = self.conf['params'] positions = self.conf['positions'] dim = coord.shape[0] topos = [] # periodically enlarge coordinates N = np.array(coord.shape[1:]) cop = np.empty(np.hstack([dim, 3*N])) mapY = np.array([-1, 0, 1]) for dd in np.arange(dim): Nshape = np.ones(dim, dtype=np.int32) Nshape[dd] = 3*N[dd] Nrep = 3*N Nrep[dd] = 1 vec = np.repeat(mapY*self.Y[dd], N[dd]) Ymat = np.tile(np.reshape(vec, Nshape), Nrep) cop[dd] = np.tile(coord[dd], 3*np.ones(dim)) + Ymat mapY = np.array([-1, 0, 1]) Yiter = mapY[np.newaxis] for ii in np.arange(1, dim): Yiter = np.vstack([np.repeat(Yiter, 3, axis=1), np.tile(mapY, Yiter.shape[1])]) for ii, kind in enumerate(inclusions): if kind in inclusion_keys['cube']: param = np.array(params[ii], dtype=np.float64) pos = np.array(positions[ii], dtype=np.float64) topos.append(np.zeros(cop.shape[1:])) for Ycoef in Yiter.T: Ym = self.Y*Ycoef topo_loc = np.ones(cop.shape[1:]) for dd in np.arange(dim): topo_loc *= ((cop[dd]-pos[dd]+Ym[dd]) > -param[dd]/2) topo_loc *= ((cop[dd]-pos[dd]+Ym[dd]) <= param[dd]/2) topos[ii] += topo_loc topos[ii] = decrease(topos[ii], N) elif kind in inclusion_keys['ball']: pos = np.array(positions[ii], dtype=np.float64) topos.append(np.zeros(cop.shape[1:])) for Ycoef in Yiter.T: Ym = self.Y*Ycoef topo_loc = np.ones(cop.shape[1:]) norm2 = 0. # square of norm for dd in np.arange(dim): norm2 += (cop[dd]-pos[dd]-Ym[dd])**2 topos[ii] += (norm2**0.5 < params[ii]/2) topos[ii] = decrease(topos[ii], N) elif kind in inclusion_keys['pyramid']: param = np.array(params[ii], dtype=np.float64) pos = np.array(positions[ii], dtype=np.float64) topos.append(np.zeros(cop.shape[1:])) for Ycoef in Yiter.T: Ym = self.Y*Ycoef topo_loc = np.ones(cop.shape[1:]) shp = cop[0].shape tri = lambda t, h: np.maximum(1-np.abs(t)/h, np.zeros(shp)) for dd in np.arange(dim): topo_loc *= tri(cop[dd]-pos[dd]+2*Ym[dd], param[dd]/2.) topos[ii] += topo_loc topos[ii] = decrease(topos[ii], N) elif kind == 'otherwise': topos.append(np.ones(coord.shape[1:])) for jj in np.arange(len(topos)-1): topos[ii] -= topos[jj] if not (topos[ii] >= 0).all(): raise NotImplementedError("Overlapping inclusions!") elif kind == 'all': topos.append(np.ones(coord.shape[1:])) else: msg = "Inclusion (%s) is not implemented." % (kind) raise NotImplementedError(msg) return topos
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']: 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: if P is None and 'P' in self.conf: P = self.conf['P'] coord = Grid.get_coordinates(P, self.Y) vals = self.evaluate(coord) dim = vals.d 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(np.hstack([dim, dim, Nbar])) for m in np.arange(dim): for n in np.arange(dim): hAM0 = DFT.fftnc(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 * factor - 1) hAM = decrease(hAM0per, Nbar) else: raise ValueError() pNbar = np.prod(Nbar) """ if DFT is normalized in accordance with articles there should be np.prod(M) instead of np.prod(Nbar)""" val[m, n] = np.real(pNbar * DFT.ifftnc(Wraw * hAM, Nbar)) name = 'A_Ga_o%d_P%d' % (order, P.max()) return Matrix(name=name, val=val, Fourier=False)
def get_topologies(self, coord): """ Returns topologies at coordinates (coord). By a topology, it is understood a characteristic function (ones and zeros at coord) of individual inclusions (square, circle, etc.) usually defined in input file. """ inclusions = self.conf['inclusions'] params = self.conf['params'] positions = self.conf['positions'] dim = coord.shape[0] topos = [] # periodically enlarge coordinates N = np.array(coord.shape[1:]) cop = np.empty(np.hstack([dim, 3 * N])) mapY = np.array([-1, 0, 1]) for dd in np.arange(dim): Nshape = np.ones(dim, dtype=np.int32) Nshape[dd] = 3 * N[dd] Nrep = 3 * N Nrep[dd] = 1 vec = np.repeat(mapY * self.Y[dd], N[dd]) Ymat = np.tile(np.reshape(vec, Nshape), Nrep) cop[dd] = np.tile(coord[dd], 3 * np.ones(dim)) + Ymat mapY = np.array([-1, 0, 1]) Yiter = mapY[np.newaxis] for ii in np.arange(1, dim): Yiter = np.vstack( [np.repeat(Yiter, 3, axis=1), np.tile(mapY, Yiter.shape[1])]) for ii, kind in enumerate(inclusions): if kind in inclusion_keys['cube']: param = np.array(params[ii], dtype=np.float64) pos = np.array(positions[ii], dtype=np.float64) topos.append(np.zeros(cop.shape[1:])) for Ycoef in Yiter.T: Ym = self.Y * Ycoef topo_loc = np.ones(cop.shape[1:]) for dd in np.arange(dim): topo_loc *= ((cop[dd] - pos[dd] + Ym[dd]) > -param[dd] / 2) topo_loc *= ((cop[dd] - pos[dd] + Ym[dd]) <= param[dd] / 2) topos[ii] += topo_loc topos[ii] = decrease(topos[ii], N) elif kind in inclusion_keys['ball']: pos = np.array(positions[ii], dtype=np.float64) topos.append(np.zeros(cop.shape[1:])) for Ycoef in Yiter.T: Ym = self.Y * Ycoef topo_loc = np.ones(cop.shape[1:]) norm2 = 0. # square of norm for dd in np.arange(dim): norm2 += (cop[dd] - pos[dd] - Ym[dd])**2 topos[ii] += (norm2**0.5 < params[ii] / 2) topos[ii] = decrease(topos[ii], N) elif kind in inclusion_keys['pyramid']: param = np.array(params[ii], dtype=np.float64) pos = np.array(positions[ii], dtype=np.float64) topos.append(np.zeros(cop.shape[1:])) for Ycoef in Yiter.T: Ym = self.Y * Ycoef topo_loc = np.ones(cop.shape[1:]) shp = cop[0].shape tri = lambda t, h: np.maximum(1 - np.abs(t) / h, np.zeros(shp)) for dd in np.arange(dim): topo_loc *= tri(cop[dd] - pos[dd] + 2 * Ym[dd], param[dd] / 2.) topos[ii] += topo_loc topos[ii] = decrease(topos[ii], N) elif kind == 'otherwise': topos.append(np.ones(coord.shape[1:])) for jj in np.arange(len(topos) - 1): topos[ii] -= topos[jj] if not (topos[ii] >= 0).all(): raise NotImplementedError("Overlapping inclusions!") elif kind == 'all': topos.append(np.ones(coord.shape[1:])) else: msg = "Inclusion (%s) is not implemented." % (kind) raise NotImplementedError(msg) return topos