diff --git a/ANN_Data_Generator.py b/ANN_Data_Generator.py index 4168fe9a75a8cf1cb072b30294f454ff95aa462f..f9d2e67259fc5da81db468877b4aeb62809150e7 100644 --- a/ANN_Data_Generator.py +++ b/ANN_Data_Generator.py @@ -13,15 +13,20 @@ from Quadrature import Gauss from Basis_Function import OrthonormalLegendre -basis_list = [OrthonormalLegendre(pol_deg) for pol_deg in range(5)] -quadrature_list = [Gauss({'num_nodes': pol_deg+1}) for pol_deg in range(5)] - - class TrainingDataGenerator: """Class for training data generator. Generates random training data for given initial conditions. + Attributes + ---------- + basis_list : list + List of basis instances for degree 1 to 4. + quadrature_list : list + List of Gauss quadrature instances for degree 2 to 5. + mesh_list : list + List of Mesh instances for 2**(3 to 8) cells. + Methods ------- build_training_data(num_samples) @@ -41,8 +46,13 @@ class TrainingDataGenerator: Size of training data array. Default: 3. """ - self._left_bound = left_bound - self._right_bound = right_bound + self._basis_list = [OrthonormalLegendre(pol_deg) + for pol_deg in range(5)] + self._quadrature_list = [Gauss({'num_nodes': pol_deg+1}) + for pol_deg in range(5)] + self._mesh_list = [Mesh(left_bound=left_bound, right_bound=right_bound, + num_ghost_cells=0, num_grid_cells=2**exp) + for exp in range(3, 9)] # Set stencil length if stencil_length % 2 == 0: @@ -147,6 +157,8 @@ class TrainingDataGenerator: # Create normalized input data norm_input_matrix = self._normalize_data(input_matrix) + # print(input_matrix) + # print(norm_input_matrix) return {'input_data.raw': input_matrix, 'output_data': output_matrix, 'input_data.normalized': norm_input_matrix} @@ -197,28 +209,28 @@ class TrainingDataGenerator: initial_condition.randomize( initial_conditions[function_id]['config']) - # Build random stencil of given length - interval, centers, spacing = self._build_stencil() - left_bound, right_bound = interval - centers = [center[0] for center in centers] + # Build mesh for random stencil of given length + mesh = self._mesh_list[int(np.random.randint( + 3, high=9, size=1))-3].random_stencil(self._stencil_length) # Induce adjustment to capture troubled cells adjustment = 0 if initial_condition.is_smooth() \ - else centers[self._stencil_length//2] - initial_condition.induce_adjustment(-spacing[0]/3) + else mesh.non_ghost_cells[self._stencil_length//2] + initial_condition.induce_adjustment(-mesh.cell_len/3) + # print(initial_condition.is_smooth()) + # print(mesh.interval_len, mesh.non_ghost_cells, mesh.cell_len) + # print(adjustment, -mesh.cell_len/3) + # print() # Calculate basis coefficients for stencil polynomial_degree = np.random.randint(1, high=5) - - mesh = Mesh(num_grid_cells=self._stencil_length, num_ghost_cells=2, - left_bound=left_bound, right_bound=right_bound) projection = do_initial_projection( initial_condition=initial_condition, mesh=mesh, - basis=basis_list[polynomial_degree], - quadrature=quadrature_list[polynomial_degree], + basis=self._basis_list[polynomial_degree], + quadrature=self._quadrature_list[polynomial_degree], adjustment=adjustment) - - input_data[i] = basis_list[ + # print(projection) + input_data[i] = self._basis_list[ polynomial_degree].calculate_cell_average( projection=projection[:, 1:-1], stencil_length=self._stencil_length, @@ -239,42 +251,6 @@ class TrainingDataGenerator: return input_data, output_data - def _build_stencil(self): - """Builds random stencil. - - Calculates fixed number of cell centers around a random point in a - given 1D domain. - - Returns - ------- - interval : ndarray - List containing left and right bound of interval. - stencil : ndarray - List of cell centers in stencil. - grid_spacing : float - Length of cell in grid. - - """ - # Select random cell length - grid_spacing = 2 / (2 ** np.random.randint(3, high=9, size=1)) - - # Pick random point between left and right bound - point = np.random.uniform(self._left_bound, self._right_bound) - - # Adjust grid spacing if necessary for stencil creation - while point - self._stencil_length/2 * grid_spacing < self._left_bound\ - or point + self._stencil_length/2 * \ - grid_spacing > self._right_bound: - grid_spacing /= 2 - - # Build x-point stencil - interval = np.array([point - self._stencil_length/2 * grid_spacing, - point + self._stencil_length/2 * grid_spacing]) - stencil = np.array([point + factor * grid_spacing - for factor in range(-(self._stencil_length//2), - self._stencil_length//2 + 1)]) - return interval, stencil, grid_spacing - @staticmethod def _normalize_data(input_data): """Normalizes data. diff --git a/DG_Approximation.py b/DG_Approximation.py index c44669b7de9cfea7f551e41feb13f8e7068ff52f..d0acc65730f0cd9efe79f01f759f833addb7ab92 100644 --- a/DG_Approximation.py +++ b/DG_Approximation.py @@ -12,10 +12,16 @@ TODO: Contemplate containing coarse mesh generation in Mesh TODO: Contemplate extracting boundary condition from InitialCondition TODO: Contemplate containing boundary condition in Mesh TODO: Ask whether all quadratures depend on freely chosen num_nodes +TODO: Contemplate saving each IC separately +TODO: Contemplate removing TrainingDataGenerator class Urgent: -TODO: Remove unnecessary instance variables from TrainingDataGenerator -TODO: Find error in centering for ANN training +TODO: Remove unnecessary instance variables from TrainingDataGenerator -> Done +TODO: Fix bug during adjustment setting -> Done +TODO: Move stencil building to Mesh -> Done +TODO: Investigate self-referencing in classes +TODO: Remove stencil_length as instance variable +TODO: Find errors in centering for ANN training TODO: Adapt TCD from Soraya (Dropbox->...->TEST_troubled-cell-detector->Troubled_Cell_Detector) TODO: Add TC condition to only flag cell if left-adjacent one is flagged as diff --git a/projection_utils.py b/projection_utils.py index 9e3a9d4bcc8166dc62c0fdaedffef18df6b5c468..39fe4c7e465f95eca3cf76f5df634b9375e0e4a8 100644 --- a/projection_utils.py +++ b/projection_utils.py @@ -93,13 +93,40 @@ class Mesh: """Return the cell centers of the mesh (excluding ghost cells).""" return self.cells[self._num_ghost_cells:-self._num_ghost_cells] - def create_data_dict(self): + def create_data_dict(self) -> dict: """Return dictionary with data necessary to construct mesh.""" return {'num_grid_cells': self._num_grid_cells, 'left_bound': self._left_bound, 'right_bound': self._right_bound, 'num_ghost_cells': self._num_ghost_cells} + def random_stencil(self, stencil_length: int) -> 'Mesh': + """Return random stencil. + + Build mesh with given number of cell centers around a random point + in the underlying interval. + + Returns + ------- + Mesh object + Mesh of given size around random point. + + """ + # Pick random point between left and right bound + point = np.random.uniform(self._left_bound, self._right_bound) + + # Adjust grid spacing to be within interval if necessary + # creation + grid_spacing = self.cell_len + while point - stencil_length/2 * grid_spacing < self._left_bound \ + or point + stencil_length/2 * grid_spacing > self._right_bound: + grid_spacing /= 2 + + # Return new mesh instance + return Mesh(left_bound=point - stencil_length/2 * grid_spacing, + right_bound=point + stencil_length/2 * grid_spacing, + num_grid_cells=stencil_length, num_ghost_cells=2) + def calculate_approximate_solution( projection: ndarray, points: ndarray, polynomial_degree: int,