def __init__( self, domain, beta, k, grid, power_spectrum=lambda q: 2/(q**4 + 1), rho=1, verbosity=0): super().__init__() self.beta = beta self._domain = (domain, ) self.fft = nifty5.FFTOperator(self._domain) self.h_space = self.fft.target[0] self.grid = grid self.k = k self.rho = rho B_h = nifty5.create_power_operator( domain=self.h_space, power_spectrum=power_spectrum) self.B = nifty5.SandwichOperator.make(self.fft, B_h) # the diagonal operator rho*e^beta rho_e_beta = np.zeros(domain.shape[0]) for i, pos in enumerate(self.grid): rho_e_beta[pos] = ( self.rho*np.exp(self.beta.val[pos])) rho_e_beta_field = nifty5.Field(domain=domain, val=rho_e_beta) self.rho_e_beta_diag = nifty5.DiagonalOperator( domain=self._domain, diagonal=rho_e_beta_field)
def apply(self, x, mode): self._check_input(x, mode) v = x.val.copy() for i in self._domain.axes[self._space]: lead = (slice(None), ) * i v, loc = ift.dobj.ensure_not_distributed(v, (i, )) loc[lead + (slice(None), )] += loc[lead + (slice(None, None, -1), )] loc /= 2 return ift.Field(self.target, ift.dobj.ensure_default_distributed(v))
def get_gradient_beta_terms(self): # gradient wrt beta # -k term1_val = np.zeros(self.len_s_space) # rho(e^beta_vec) term2_val = np.zeros(self.len_s_space) for i, pos in enumerate(self.grid): term1_val[pos] = -self.k[i] term2_val[pos] = self.rho*np.exp(self.beta_vector[i]) term1 = nifty5.Field(domain=self.s_space, val=term1_val) term2 = nifty5.Field(domain=self.s_space, val=term2_val) # beta.B^(-1) term3 = self.B_inv.adjoint_times(self.beta) return ( self.term_factors[1]*term1, self.term_factors[2]*term2, self.term_factors[3]*term3)
def get_Lambda_modes(self, speedup=False): # this is an array of matrices: # Lambda_mode(z)_ij = (1/2pi) (cos(z(x_i-x_j)) + sin(z(x_i + x_j)) ) self.Lambda_modes_list = list() if not False: # conventional way for k in range(self.len_p_space): p_spec = np.zeros(self.len_p_space) p_spec[k] = np.exp(self.tau_f.val[k]) p_spec[k] = 1 Lambda_h = nifty5.create_power_operator( domain=self.h_space, power_spectrum=nifty5.Field(domain=self.p_space, val=p_spec)) Lambda_kernel = nifty5.SandwichOperator.make( self.fft, Lambda_h) Lambda_kernel_matrix = probe_operator(Lambda_kernel) Lambda_modes = np.zeros((self.N, self.N)) for i in range(self.N): for j in range(i + 1): Lambda_modes[i, j] = Lambda_kernel_matrix[ self.x_indices[i], self.x_indices[j]] if i != j: Lambda_modes[j, i] = Lambda_kernel_matrix[ self.x_indices[i], self.x_indices[j]] self.Lambda_modes_list.append(Lambda_modes) else: # based on the thought that we are just dealing with single # fourier modes, we can calculate these directly Lambda_modes = np.zeros((self.N, self.N)) for i in range(self.N): for j in range(i + 1): x_i_index = self.x_indices[i] x_j_index = self.x_indices[j] a = (self.grid_coordinates[x_i_index] - self.grid_coordinates[x_j_index]) # dirty hack, if we take cos((x-y)*2*pi) we get the # desired result Lambda_modes[i, j] = np.cos(a * 2 * np.pi) if i != j: Lambda_modes[j, i] = np.cos(a * 2 * np.pi) # use the relation cos(nx) = T_n(cos(x)) where T_n is the nth # chebyhsev polynomial for i, z in enumerate(self.p_space[0].k_lengths): factor = 2 * self.len_s_space**(-2) if i == 0: factor = factor / 2 if i == (self.len_p_space - 1): factor = factor / 2 z = int(z) self.Lambda_modes_list.append( factor * np.polynomial.Chebyshev(coef=[0] * z + [1])(Lambda_modes))
def SlopeSpectrumOperator(target, m=0, n=0, sigma_m=.1, sigma_n=.1): codomain = target.get_default_codomain() pos_diagonals = np.ones(target.shape[0]) pos_diagonals[target.shape[0] // 2 + 1:] = -1 flipper = ift.DiagonalOperator( ift.Field(ift.DomainTuple.make(codomain), pos_diagonals)) slope = LinearSlopeOperator(target.get_default_codomain()) mean = np.array([m, n]) sig = np.array([sigma_m, sigma_n]) mean = ift.Field.from_global_data(slope.domain, mean) sig = ift.Field.from_global_data(slope.domain, sig) linear_operator = flipper @ slope @ ift.Adder(mean) @ ift.makeOp(sig) return linear_operator.ducktape('slope')
def probe_operator(operator): """ probe a symmetric operator in dim terations by just applying times to unit vectors. volume factors not included """ domain = operator.domain[0] dim = domain.shape[0] operator_matrix = np.zeros((dim, dim)) for i in range(dim): a = nifty5.Field(domain=domain, val=np.zeros(dim)) a.val[i] = 1 right = operator.times(a) operator_matrix[:, i] = np.array(right.val) return operator_matrix
def test_err(): s1 = ift.RGSpace((10, )) s2 = ift.RGSpace((11, )) f1 = ift.Field.full(s1, 27) with assert_raises(ValueError): f2 = ift.Field(ift.DomainTuple.make(s2), f1.val) with assert_raises(TypeError): f2 = ift.Field.full(s2, "xyz") with assert_raises(TypeError): if f1: pass with assert_raises(TypeError): f1.full((2, 4, 6)) with assert_raises(TypeError): f2 = ift.Field(None, None) with assert_raises(TypeError): f2 = ift.Field(s1, None) with assert_raises(ValueError): f1.imag with assert_raises(TypeError): f1.vdot(42) with assert_raises(ValueError): f1.vdot(ift.Field.full(s2, 1.)) with assert_raises(TypeError): ift.full(s1, [2, 3]) with assert_raises(TypeError): ift.Field(s2, [0, 1]) with assert_raises(TypeError): f1.outer([0, 1]) with assert_raises(ValueError): f1.extract(s2) with assert_raises(TypeError): f1 += f1 f2 = ift.Field.full(s2, 27) with assert_raises(ValueError): f1 + f2
def get_del_B(self): self.del_B_inv_list = list() for i in range(self.len_p_space): p_spec = np.zeros(self.len_p_space) p_spec[i] = np.exp(-self.tau_beta.val[i]) del_B_inv_h = nifty5.create_power_operator( domain=self.h_space, power_spectrum=nifty5.Field( domain=self.p_space, val=p_spec)) del_B_inv = nifty5.SandwichOperator.make( self.fft, del_B_inv_h) self.del_B_inv_list.append(del_B_inv)
def get_gradient_terms(self): """ calculate the terms for the gradient wrt. tau_f and return them as a tuple """ # tr(G Lambda) term1 = 0.5 * nifty5.Field(domain=self.p_space, val=np.array([ np.trace(self.G @ self.Lambdas[i]) for i in range(self.len_p_space) ])) # y.G.Lambda.G.y term2 = -0.5 * nifty5.Field.from_global_data( domain=self.p_space, arr=np.array([ self.y @ self.G @ self.Lambdas[i] @ self.G @ self.y for i in range(self.len_p_space) ])) term3 = self.smoothness_operator_f(self.position) return (self.term_factors[0] * term1, self.term_factors[1] * term2, self.term_factors[2] * term3)
def __init__( self, position, k, x, y, grid, sigma_f=1, sigma_beta=1, sigma_eta=1, rho=1, mode='multifield', single_fields=None, Lambda_modes_list=None, term_factors=[1]*11, ): super().__init__(position=position) self.domain = position.domain self.k, self.x, self.y = k, x, y self.N = len(self.x) self.sigma_beta = sigma_beta self.sigma_f = sigma_f self.sigma_eta = sigma_eta self.rho = rho self.mode = mode self.fields = single_fields if mode == 'multifield': self.beta = position.val['beta'] self.tau_beta = position.val['tau_beta'] self.tau_f = position.val['tau_f'] self.eta = position.val['eta'] else: self.fields[mode] = position self.beta = self.fields['beta'] self.tau_beta = self.fields['tau_beta'] self.tau_f = self.fields['tau_f'] self.eta = self.fields['eta'] self.s_space = self.beta.domain[0] self.h_space = self.s_space.get_default_codomain() self.p_space = self.tau_f.domain self.len_p_space = self.p_space.shape[0] self.len_s_space = self.s_space.shape[0] self.grid = grid self.grid_coordinates = [i*self.s_space.distances[0] for i in range( self.s_space.shape[0])] # beta_vector is the R^N_bins vector with beta field values at the grid # positions self.beta_vector = np.array([self.beta.val[i] for i in self.grid]) self.fft = nifty5.FFTOperator(domain=self.s_space, target=self.h_space) self.F_h = nifty5.create_power_operator( domain=self.h_space, power_spectrum=nifty5.exp(self.tau_f)) self.B_inv_h = nifty5.create_power_operator( domain=self.h_space, power_spectrum=nifty5.exp(-self.tau_beta)) self.B_inv = nifty5.SandwichOperator.make(self.fft, self.B_inv_h) self.F = nifty5.SandwichOperator.make(self.fft, self.F_h) self.F_matrix = probe_operator(self.F) self.F_tilde = np.zeros((self.N, self.N)) for i in range(self.N): for j in range(i+1): self.F_tilde[i, j] = self.F_matrix[ self.x_indices[i], self.x_indices[j]] if i != j: self.F_tilde[j, i] = self.F_matrix[ self.x_indices[i], self.x_indices[j]] self.exp_hat_eta_x = np.diag([np.exp( self.eta.val[self.x_indices[i]]) for i in range(self.N)]) self.G = np.linalg.inv(self.F_tilde + self.exp_hat_eta_x) self.smoothness_operator_f = nifty5.SmoothnessOperator( domain=self.p_space, strength=1/self.sigma_f) self.smoothness_operator_beta = nifty5.SmoothnessOperator( domain=self.p_space, strength=1/self.sigma_beta) # second derivative of eta nabla_nabla_eta = np.zeros(self.eta.val.shape) scipy.ndimage.laplace( input=self.eta.val, output=nabla_nabla_eta) self.nabla_nabla_eta_field = nifty5.Field( domain=self.s_space, val=nabla_nabla_eta) if Lambda_modes_list is None: self.get_Lambda_modes(speedup=True) else: self.Lambda_modes_list = Lambda_modes_list self.term_factors = term_factors self.get_Lambdas() self.get_del_B() self.get_del_exp_eta_x()
def gradient(self): gradient_terms = self.get_gradient_terms() gradient = np.sum(np.array(gradient_terms), axis=0) return nifty5.Field(domain=self.s_space, val=gradient)