def __init__(self, initial_value: np.ndarray, coarse_x: np.ndarray, coarse_y: np.ndarray, fine_x: np.ndarray, fine_y: np.ndarray, symmetry: np.ndarray = np.array([0, 0]), periodicity: np.ndarray = np.array([0, 0]), periods: np.ndarray = np.array([0, 0]), lower_bound: Union[float, List[float]] = 0, upper_bound: Union[float, List[float]] = 1, bounds: List[float] = None) -> None: self.x_z = fine_x self.y_z = fine_y self.x_p = coarse_x self.y_p = coarse_y self.beta = 1 / 3 # relaxation factor of the fabrication constraint self.k = 4 # factor in the exponential in the sigmoid function used to discretize self.geometry_matrix, self.reverse_geometry_matrix = cubic_utils.make_geometry_matrix_cubic( (len(coarse_x), len(coarse_y)), symmetry, periodicity, periods) # correct the initial value if isinstance(initial_value, (float, int, complex)): self.vector = initial_value * np.ones( self.geometry_matrix.shape[1]) elif len(initial_value) == self.reverse_geometry_matrix.shape[0]: self.vector = initial_value elif len(initial_value) == self.reverse_geometry_matrix.shape[1]: self.vector = self.reverse_geometry_matrix @ initial_value else: raise ValueError('Invalid initial value') # Make the interpolation matrix. #periodicity_phi2f = np.logical_and(periodicity, np.logical_not(periods)) phi2f, _, _ = cubic_utils.CubicMatrices(self.x_z, self.y_z, self.x_p, self.y_p, periodicity) self.vec2f = phi2f @ self.geometry_matrix # Set bounds if bounds: self.lower_bound = bounds[0] self.upper_bound = bounds[1] else: self.lower_bound = lower_bound self.upper_bound = upper_bound
def __init__(self, initial_value: np.ndarray, coarse_x: np.ndarray, coarse_y: np.ndarray, fine_x: np.ndarray, fine_y: np.ndarray, symmetry: np.ndarray = np.array([0, 0]), periodicity: np.ndarray = np.array([0, 0]), periods: np.ndarray = np.array([0, 0]), lower_bound: Union[float, List[float]] = -np.inf, upper_bound: Union[float, List[float]] = np.inf, bounds: List[float] = None, scale: float = 1.75) -> None: self.x_z = fine_x self.y_z = fine_y self.x_p = coarse_x self.y_p = coarse_y self.beta = 1 / 3 # relaxation factor of the fabrication constraint self.k = 4 # factor in the exponential in the sigmoid function used to discretize self.scale_deriv = scale self.fine_x_grid, self.fine_y_grid = np.meshgrid( fine_x, fine_y, indexing='ij') self.geometry_matrix, self.reverse_geometry_matrix = cubic_utils.make_geometry_matrix_hermite( (len(coarse_x), len(coarse_y)), symmetry, periodicity, periods) # correct the initial value self.derivative_matrix = cubic_utils.idxdydxy_matrix( coarse_x, coarse_y, deriv_scaling=np.array([ 1, scale * np.diff(fine_x).mean(), scale ** 2 * np.diff(fine_x).mean() ** 2 ])) # correct the initial value if isinstance(initial_value, (float, int, complex)): self.vector = initial_value * np.ones(self.geometry_matrix.shape[1]) elif len(initial_value) == self.geometry_matrix.shape[1]: self.vector = initial_value elif len(initial_value) == self.geometry_matrix.shape[0]: self.vector = self.reverse_geometry_matrix @ initial_value elif len(initial_value) == self.derivative_matrix.shape[1]: self.vector = self.reverse_geometry_matrix @ \ self.derivative_matrix @ initial_value # TODO vcruysse: account for the following cases # elif len(initial_value) == symmetry_matrix.shape[1]*4: # elif len(initial_value) == symmetry_matrix.shape[1]: # elif len(initial_value) == periodic_matrix_n.shape[0]*4: # elif len(initial_value) == periodic_matrix_n.shape[0]: else: raise ValueError('Invalid initial value') # Make the interpolation matrix. phi2f, _, _ = cubic_utils.CubicMatrices( fine_x, fine_y, coarse_x, coarse_y, periodicity, derivatives=True, deriv_scaling=np.array([ 1, scale * np.diff(fine_x).mean(), scale ** 2 * np.diff(fine_x).mean() ** 2 ])) self.vec2f = phi2f @ self.geometry_matrix # Set bounds if bounds: self.lower_bound = bounds[0] self.upper_bound = bounds[1] else: self.lower_bound = lower_bound self.upper_bound = upper_bound