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