def __init__(self, efloat_mode="float"): self.efloat_mode = efloat_mode self.efloat = EFloat(efloat_mode) self.alphas = [] self.betas = [] self.unique_id_string = ""
def _tanhsinh(s, h): N = s k = numpy.array(range(-N//2, N//2+1)) if floatmode == "float": x = numpy.tanh(0.5*numpy.pi*numpy.sinh(k*h)) w = 0.5*h*numpy.pi*numpy.cosh(k*h)/numpy.power(numpy.cosh(0.5*numpy.pi*numpy.sinh(k*h)), 2.0) # To interval [0;1] x = (x+1.0)*0.5 w *= 0.5 elif floatmode == "mpfloat": efloat_mode="mpfloat" efloat = ef.EFloat(efloat_mode) import mpmath as mp x = efloat.fromArray(numpy.zeros([N])) w = efloat.fromArray(numpy.zeros([N])) for i in range(N): x[i,0] = mp.mp.tanh(0.5*mp.mp.pi*mp.mp.sinh(k[i]*h)) w[i,0] = 0.5*h*mp.mp.pi*mp.mp.cosh(k[i]*h)/mp.mp.power(mp.mp.cosh(0.5*mp.mp.pi*mp.mp.sinh(k[i]*h)), 2.0) # To interval [0;1] x = (x+1.0)*0.5 w *= 0.5 x = numpy.array(x.tolist(), dtype=float)[:,0] w = numpy.array(w.tolist(), dtype=float)[:,0] return x, w
def toFloat(self): c = REXICoefficients() c.efloat = EFloat("float") c.function_name = self.function_name if self.efloat != None: if self.efloat.abs(self.efloat.im(self.gamma)) > 1e-10: print("WARNING") print("WARNING") print("WARNING") print("WARNING: Imaginary value " + str(self.efloat.im(self.gamma)) + " should be close to zero") print("WARNING") print("WARNING") print("WARNING") c.gamma = float(self.efloat.re(self.gamma)) else: c.gamma = float(self.gamma.real) c.alphas = [complex(a) for a in self.alphas] c.betas = [complex(b) for b in self.betas] c.unique_id_string = self.unique_id_string return c
def __init__(self, efloat_mode="float"): self.efloat_mode = efloat_mode self.efloat = EFloat(efloat_mode) self.unique_id_string = "" self.section_factory = SectionFactory() self.section_list = []
def main(): # double precision floatmode = 'float' # multiprecision floating point numbers #floatmode = 'mpfloat' # load float handling library efloat = ef.EFloat(floatmode) h = efloat.to(0.2) M = 64 print("M: " + str(M)) print("h: " + str(h)) print("") for half in [False, True]: print("*" * 80) print("* Original REXI coefficients") rexi = TREXI( N=M, h=h, function_name="phi0", reduce_to_half=half, floatmode=floatmode, ) print("") print("*" * 80) print("Running tests...") rexi.runTests() print("*" * 80) print("* REXI coefficients based on original REXI mu") print("*" * 80) rexi = TREXI( N=M, h=h, ratgauss_basis_function_spacing=1.0, ratgauss_basis_function_rat_shift=efloat.to( '-4.31532151087502402475593044073320925235748291015625'), reduce_to_half=half, floatmode=floatmode, ) print("*" * 80) print("Rational approx. of Gaussian data:") #rexi.ratgauss_coeffs.print_coefficients() print("") print("*" * 80) print("Running tests...") rexi.runTests()
def __init__( self, gaussphi0_N, # required argument gaussphi0_basis_function_spacing, # required argument floatmode = None ): self.efloat = ef.EFloat(floatmode) self.h = self.efloat.to(gaussphi0_basis_function_spacing) self.M = int(gaussphi0_N) self.b = [self.efloat.exp(self.h*self.h)*self.efloat.exp(-1j*(float(m)*self.h)) for m in range(-self.M, self.M+1)] # Generate dummy Gaussian function fafcoeffs = TREXI_GaussianCoefficients() fafcoeffs.function_name = 'gaussianorig' fafcoeffs.function_scaling = self.efloat.to(1.0)
def __init__( self, function_name = "phi0", efloat_mode = None ): self.efloat = ef.EFloat(efloat_mode) self.function_name = function_name self.function_complex = True if self.efloat.floatmode == 'mpfloat': import mpmath as mp # Set numerical threshold to half of precision self.epsthreshold = 1e-15 else: self.epsthreshold = 1e-10 # Exponential integrator: phi0 if self.function_name[0:3] == 'phi': N = int(self.function_name[3:]) def fun(x): return self.phiN(N, x) self.eval = fun if self.function_complex: self.is_real_symmetric = True self.is_complex_conjugate_symmetric = True else: self.is_real_symmetric = True self.is_complex_conjugate_symmetric = False elif self.function_name[0:3] == 'ups': N = int(self.function_name[3:]) if self.efloat.floatmode == 'mpfloat': import mpmath as mp # Set numerical threshold to half of precision self.epsthreshold = 1e-10 else: self.epsthreshold = 1e-10 if N == 1: # # Setup \upsilon_1 for EDTRK4 # See document notes_on_time_splitting_methods.lyx # def fun(x): K = x if abs(x) < self.epsthreshold: return self.efloat.to(1.0)/self.efloat.to(2.0*3.0) else: return (-self.efloat.to(4.0)-K+self.efloat.exp(K)*(self.efloat.to(4.0)-self.efloat.to(3.0)*K+K*K))/(K*K*K) self.eval = fun if self.function_complex: self.is_real_symmetric = True self.is_complex_conjugate_symmetric = True else: self.is_real_symmetric = True self.is_complex_conjugate_symmetric = False elif N == 2: # # Setup \upsilon_2 for EDTRK4 # See document notes_on_time_splitting_methods.lyx # def fun(x): K = x if abs(x) < self.epsthreshold: return self.efloat.to(1.0)/self.efloat.to(2.0*3.0) else: return (self.efloat.to(2.0)+1.0*K+self.efloat.exp(K)*(self.efloat.to(-2.0)+K))/(K*K*K) self.eval = fun if self.function_complex: self.is_real_symmetric = True self.is_complex_conjugate_symmetric = True else: self.is_real_symmetric = True self.is_complex_conjugate_symmetric = False elif N == 3: # # Setup \upsilon_3 for EDTRK4 # See document notes_on_time_splitting_methods.lyx # def fun(x): K = x if abs(x) < self.epsthreshold: return self.efloat.to(1.0)/self.efloat.to(2.0*3.0) else: return (-self.efloat.to(4.0) - 3.0*K - K*K + self.efloat.exp(K)*(self.efloat.to(4.0)-K))/(K*K*K) self.eval = fun if self.function_complex: self.is_real_symmetric = True self.is_complex_conjugate_symmetric = True else: self.is_real_symmetric = True self.is_complex_conjugate_symmetric = False else: print("Unknown ups function "+str(N)) sys.exit(1) else: print("Unknown basis function "+str(self.function_name)) sys.exit(1)
def __init__( self, efloat_mode = None, ): self.efloat = ef.EFloat(efloat_mode)
def _golubwelsch(n, lo=-1, hi=1, radau=False): if floatmode == "float": beta = .5 / numpy.sqrt(1-(2*(numpy.arange(1,n)))**(-2.)) # 3-term recurrence coeffs T = numpy.diag(beta,1) + numpy.diag(beta,-1); # Jacobi matrix if radau: # Eq. 2.4 of Gautschi, Gauss–Radau formulae for Jacobi and Laguerre weight functions, 2000 if n == 1: T[-1,-1] = 1 else: T[-1,-1] = 1 - 2*(n-1)**2 / (2*(n-1)*(2*(n-1)+1)) D, V = numpy.linalg.eigh(T) # Eigenvalue decomposition i = numpy.argsort(D) # Legendre points x = D[i] w = 2*V[0,i]**2 # Quadrature weights x = 0.5*((hi+lo) + (hi-lo)*x) w = 0.5*(hi-lo)*w elif floatmode == "mpfloat": efloat_mode="mpfloat" efloat = ef.EFloat(efloat_mode) T = efloat.fromArray(numpy.zeros([n,n])) for i in range(1,n): beta = .5 / efloat.sqrt(1.-(2*(i))**(-2.)) # 3-term recurrence coeffs # upper diagonal T[i,i-1] = beta # lower diagonal T[i-1,i] = beta if radau: # Eq. 2.4 of Gautschi, Gauss–Radau formulae for Jacobi and Laguerre weight functions, 2000 if n == 1: T[-1,-1] = 1 else: T[-1,-1] = 1 - 2*(n-1)**2 / (2*(n-1)*(2*(n-1)+1)) D, V = efloat.eigh(T) # Eigenvalue decomposition N = len(D) i = numpy.argsort(D) # Legendre points x = efloat.fromArray(numpy.zeros(N)) w = efloat.fromArray(numpy.zeros(N)) for i in range(len(D)): x[i] = D[i] w[i] = 2*V[0,i]**2 x[i] = 0.5*((hi+lo) + (hi-lo)*x[i]) w[i] = 0.5*(hi-lo)*w[i] x = numpy.array(x.tolist(), dtype=float)[:,0] w = numpy.array(w.tolist(), dtype=float)[:,0] else: raise Exception("Unsupported floatmode") return x, w
class ELREXI: # # Constructor # See setup(...) for documentation on parameters # def __init__(self, efloat_mode="float"): self.efloat_mode = efloat_mode self.efloat = EFloat(efloat_mode) self.alphas = [] self.betas = [] self.unique_id_string = "" def setup(self, function_name, N: int, lambda_max_real: float = None, lambda_max_imag: float = None): """ Setup coefficients for Cauchy contour integral coefficients using an ellipse with height given by lambda_max_imag and width given by lambda_max_real See doc/rexi/rexi_wit_laplace for details Args: N (int): Number of points on Cauchy contour. """ self.alphas = [] self.betas = [] self.function_name = function_name self.N = N gamma = lambda_max_imag delta = lambda_max_real r = np.sqrt((1 - delta / gamma) / (1 + delta / gamma)) d = r + (1.0 / r) self.fun = Functions(function_name, efloat_mode=self.efloat_mode) #print("Setting up ellipse:") #print("gamma: ", gamma) #print("delta: ", delta) #print("r: ", r) if lambda_max_real == None or lambda_max_imag == None: raise Exception( "ELREXI: please provide max imag and real values of contour") c1 = (gamma * self.efloat.i / d) c2 = -(gamma / d) for j in range(N): theta_j = self.efloat.pi2 * (j + self.efloat.to(0.5)) / N # sampling position of support point sn = c1 * (r * self.efloat.exp(self.efloat.i * theta_j) + (1.0 / r) * self.efloat.exp(-self.efloat.i * theta_j)) #metric term sn_prime = c2 * ( r * self.efloat.exp(self.efloat.i * theta_j) - (1.0 / r) * self.efloat.exp(-self.efloat.i * theta_j)) self.betas.append(-self.efloat.i * self.fun.eval(sn) * sn_prime / N) self.alphas.append(sn) coeffs = REXICoefficients() coeffs.alphas = self.alphas[:] coeffs.betas = self.betas[:] coeffs.gamma = 0 coeffs.function_name = self.function_name self.unique_id_string = "" self.unique_id_string += self.function_name self.unique_id_string += "_N" + str(self.N) self.unique_id_string += "_im" + str(self.efloat.re(lambda_max_imag)) self.unique_id_string += "_re" + str(self.efloat.re(lambda_max_real)) coeffs.unique_id_string = self.getUniqueId() return coeffs def getUniqueId(self): return "ELREXI_" + self.unique_id_string
class CIREXI: # # Constructor # See setup(...) for documentation on parameters # def __init__(self, efloat_mode="float"): self.efloat_mode = efloat_mode self.efloat = EFloat(efloat_mode) self.alphas = [] self.betas = [] self.unique_id_string = "" def setup(self, function_name, N: int, R: float = None, lambda_shift: complex = None, lambda_max_real: float = None, lambda_include_imag: float = None): self.alphas = [] self.betas = [] self.function_name = "" if lambda_shift != None: self.setup_shifted_circle(function_name, N=N, R=R, lambda_shift=lambda_shift) elif lambda_max_real != None: self.setup_limited_circle(function_name, N=N, lambda_max_real=lambda_max_real, lambda_include_imag=lambda_include_imag) else: self.setup_circle(function_name, N=N, R=R) coeffs = REXICoefficients() coeffs.alphas = self.alphas[:] coeffs.betas = self.betas[:] coeffs.gamma = 0 coeffs.function_name = self.function_name coeffs.unique_id_string = self.getUniqueId() return coeffs def setup_shifted_circle(self, function_name, N: int, R: float, lambda_shift: complex): """ Setup coefficients for Cauchy contour integral coefficients using a shifted circle with the shift given by lambda_shift which fulfills the constraints given by lambda_* Args: N (int): Number of points on Cauchy contour. R (float): Radius of circle for Cauchy contour lambda_shift (complex): ` Shift of center of circle on complex plane """ self.function_name = function_name self.lambda_shift = lambda_shift self.fun = Functions(function_name, efloat_mode=self.efloat_mode) for j in range(N): theta_j = self.efloat.pi2 * (j + self.efloat.to(0.5)) / N # sampling position of support point pos = R * self.efloat.exp(self.efloat.i * theta_j) # shifted position gamma_j = pos + lambda_shift self.betas.append(-self.fun.eval(gamma_j) * pos / N) self.alphas.append(-gamma_j) self.unique_id_string = "shic" self.unique_id_string += "_" + function_name self.unique_id_string += "_" + str(N) self.unique_id_string += "_" + str(self.efloat.re(lambda_shift)) self.unique_id_string += "_" + str(self.efloat.im(lambda_shift)) def setup_circle(self, function_name, N: int, R: float): """ Setup circle contour integral centered at origin Args: N (int): Number of quadrature poles R (float): Radius of circle """ self.setup_shifted_circle(function_name, N, R, 0.0) self.unique_id_string = "circ" self.unique_id_string += "_" + function_name self.unique_id_string += "_" + str(N) self.unique_id_string += "_" + str(lambda_max_real) self.unique_id_string += "_" + str(lambda_include_imag) def setup_limited_circle(self, function_name: str, N: int, lambda_max_real: float, lambda_include_imag: float): """ Setup coefficients for Cauchy contour integral coefficients circle which fulfills the constraints given by lambda_* Args: N (int): Number of points on Cauchy contour. lambda_max_real (float): Maximum allowed real number on contour. lambda_include_imag (float): Include at least this imaginary value as part of the contour. Even, if the contour has to be enlarged """ # If the maximal real number is larger than the max to be included imaginary number, set a lower value for the max real number if lambda_max_real > lambda_include_imag: lambda_max_real = lambda_include_imag x0 = lambda_max_real xm = lambda_include_imag r = (x0 * x0 + xm * xm) / (2.0 * x0) center = lambda_max_real - r self.setup_shifted_circle(function_name, N, r, center) self.unique_id_string = "limc" self.unique_id_string += "_" + str(N) self.unique_id_string += "_" + function_name self.unique_id_string += "_" + str(lambda_max_real) self.unique_id_string += "_" + str(lambda_include_imag) def getUniqueId(self): return "CIREXI_" + self.unique_id_string
def setupFloatmode(self): self.efloat = ef.EFloat(self.floatmode, self.mpfloat_digits) self.floatmode = self.efloat.floatmode
new_alphas = [] new_betas = [] self.symmetric_reduction_applied = True if not '_betafilter' in self.unique_id_string: self.unique_id_string += '_betafilter' return def eval(self, x): retval = self.gamma for i in range(len(self.alphas)): retval += self.betas[i] / (x + self.alphas[i]) return retval if __name__ == "__main__": r = REXICoefficients() r.efloat = EFloat() r.gamma = 1e-12 r.alphas.append(1j + 2.0) r.betas.append(3j + 4.0) r.write_file("/tmp/test.txt") r2 = r.toFloat()