diff --git a/DG_Approximation.py b/DG_Approximation.py index 115bf888429111f296515364e402da80e480060a..7cf73388143cd5d038e8a756fba64a04ee3d1253 100644 --- a/DG_Approximation.py +++ b/DG_Approximation.py @@ -6,6 +6,8 @@ Plotter: TODO: Double-check everything! (also with pylint, pytype, pydoc, pycodestyle) TODO: Replace loops with list comprehension if feasible TODO: Write documentation for all methods (important) +TODO: Discuss adding kwargs to attributes in documentation +TODO: Check whether documentation style is correct TODO: Check whether 'projection' is always a np.array() TODO: Check whether all instance variables sensible TODO: Use cfl_number for updating, not just time @@ -29,13 +31,81 @@ x = Symbol('x') class DGScheme(object): - """ - Do documentation here. + """Class for Discontinuous Galerkin Method. + + Approximates linear advection equation using Discontinuous Galerkin Method with + troubled-cell-based limiting. + + Attributes + ---------- + interval_len : float + Length of the interval between left and right boundary. + cell_len : float + Length of a cell in mesh. + basis : Basis object + Basis for calculation. + mesh : array + List of mesh valuation points. + inv_mass : np.array + Inverse mass matrix. + + Methods + ------- + approximate() + Approximates projection. + save_plots() + Saves plots generated during approximation process. + build_training_data(adjustment, stencil_length, initial_condition=None) + Builds training data set. - Here come some parameter. """ - def __init__(self, detector, **kwargs): + """Initializes DGScheme. + + Parameters + ---------- + detector : str + Name of troubled cell detector class. + + Other Parameters + ---------------- + wave_speed : float, optional + Speed of wave in rightward direction. Default: 1. + polynomial_degree : int, optional + Polynomial degree. Default: 2. + cfl_number : float, optional + CFL number to ensure stability. Default: 0.2. + num_grid_cells : int, optional + Number of cells in the mesh. Usually exponential of 2. Default: 64. + final_time : float, optional + Final time for which approximation is calculated. Default: 1. + left_bound : float, optional + Left boundary of interval. Default: -1. + right_bound : float, optional + Right boundary of interval. Default: 1. + verbose : boolean, optional + Flag whether commentary in console is wanted. Default: False + plot_dir : str, optional + Path to directory in which plots are saved. Default: 'test'. + history_threshold : float, optional + Threshold when history will be recorded. Default: math.ceil(0.2/cfl_number). + detector_config : dict, optional + Additional parameters for detector object. Default: {}. + init_cond : str, optional + Name of initial condition for evaluation. Default: 'Sine' + init_config : dict, optional + Additional parameters for initial condition object. Default: {}. + limiter : str, optional + Name of limiter for evaluation. Default: 'ModifiedMinMod'. + limiter_config : dict, optional + Additional parameters for limiter. object. Default: {}: + quadrature : str, optional + Name of quadrature for evaluation. Default: 'Gauss'. + quadrature_config : dict, optional + Additional parameters for quadrature object. Default: {}. + update_scheme : str, optional + Name of update scheme for evaluation. Default: 'SSPRK3'. + """ # Unpack keyword arguments self._wave_speed = kwargs.pop('wave_speed', 1) self._polynomial_degree = kwargs.pop('polynomial_degree', 2) @@ -90,12 +160,14 @@ class DGScheme(object): self._polynomial_degree, self._num_grid_cells, self._detector, self._limiter) def approximate(self): - """ - Do documentation here. + """Approximates projection. - Here come some parameter. - """ + Initializes projection and evolves it in time. Each time step consists of three parts: + A projection update, a troubled-cell detection, and limiting based on the detected cells. + At final time, result and error plots are generated and, if verbose flag is set, also + displayed. + """ projection = self._do_initial_projection(self._init_cond) time_step = abs(self._cfl_number * self._cell_len / self._wave_speed) @@ -128,11 +200,17 @@ class DGScheme(object): plt.show() def save_plots(self): + """Saves plotted results. + + Sets plot directory, if not already existing, and saves plots generated during the last + approximation. + + """ name = self._init_cond.get_name() + '__' + self._detector.get_name() + '__' \ - + self._limiter.get_name() + '__' + self._update_scheme.get_name() + '__' \ - + self._quadrature.get_name() + '__final_time_' + str(self._final_time) \ - + '__wave_speed_' + str(self._wave_speed) + '__number_of_cells_' \ - + str(self._num_grid_cells) + '__polynomial_degree_' + str(self._polynomial_degree) + + self._limiter.get_name() + '__' + self._update_scheme.get_name() + '__' \ + + self._quadrature.get_name() + '__final_time_' + str(self._final_time) \ + + '__wave_speed_' + str(self._wave_speed) + '__number_of_cells_' \ + + str(self._num_grid_cells) + '__polynomial_degree_' + str(self._polynomial_degree) # Set paths for plot files if not existing already if not os.path.exists(self._plot_dir): @@ -148,6 +226,7 @@ class DGScheme(object): plt.savefig(self._plot_dir + '/' + identifier + '/' + name + '.pdf') def _reset(self): + """Resets instance variables.""" # Set additional necessary instance variables self._interval_len = self._right_bound-self._left_bound self._cell_len = self._interval_len / self._num_grid_cells @@ -174,6 +253,24 @@ class DGScheme(object): self._inv_mass = np.array(mass_matrix) def _do_initial_projection(self, initial_condition, adjustment=0): + """Calculates initial projection. + + Calculates a projection at time step 0 and adds ghost cells on both sides of the array. + + Parameters + ---------- + initial_condition : InitialCondition object + Initial condition used for calculation. May differ from instance variable. + adjustment: float + Extent of adjustment of each evaluation point in x-direction. + + Results + ------- + np.array + Matrix containing projection of size (N+2, p+1) with N being the number of grid cells + and p being the polynomial degree. + + """ # Initialize matrix and set first entry to accommodate for ghost cell output_matrix = [0] basis_vector = self._basis.get_basis_vector() @@ -204,6 +301,16 @@ class DGScheme(object): return np.transpose(np.array(output_matrix)) def build_training_data(self, adjustment, stencil_length, initial_condition=None): + """Builds training data set. + + Initializes projection and calculates cell averages and reconstructions for it. + + Returns + ------- + np.array + Matrix containing cell averages and reconstructions for initial projection. + + """ if initial_condition is None: initial_condition = self._init_cond projection = self._do_initial_projection(initial_condition, adjustment)