# -*- coding: utf-8 -*- """ @author: Laura C. Kühle """ from abc import ABC, abstractmethod class Limiter(ABC): """Abstract class for limiting function. Methods ------- get_name() Returns string of class name. apply(projection, cell) Applies limiting to cell. """ def __init__(self, config): """Initializes Quadrature. Parameters ---------- config : dict Additional parameters for limiter. """ self._reset(config) @abstractmethod def _reset(self, config): """Resets instance variables. Parameters ---------- config : dict Additional parameters for quadrature. """ pass def get_name(self): """Returns string of class name.""" return self.__class__.__name__ @abstractmethod def apply(self, projection, cell): """Applies limiting to cell. Parameters ---------- projection : ndarray Matrix of projection for each polynomial degree. cell: int Index of cell. Returns ------- ndarray Matrix of updated projection for each polynomial degree. """ pass class NoLimiter(Limiter): """Class without any limiting. Methods ------- get_name() Returns string of class name. apply(projection, cell) Applies no limiting to cell. """ def apply(self, projection, cell): """Returns projection of cell without limiting.""" return projection[:, cell] class MinMod(Limiter): """Class for minmod limiting function. Sets projection for higher degrees to zero when forward backward, and cell slope values have not the same sign. Attributes ---------- erase_degree : int Polynomial degree up to which projection is not set to zero during limiting. Methods ------- get_name() Returns string of class name. apply(projection, cell) Applies limiting to cell. """ def _reset(self, config): """Resets instance variables. Parameters ---------- config : dict Additional parameters for quadrature. """ # Unpack necessary configurations self._erase_degree = config.pop('erase_degree', 0) def get_name(self): """Returns string of class name concatenated with the erase-degree.""" return self.__class__.__name__ + str(self._erase_degree) def apply(self, projection, cell): """Applies limiting to cell. Parameters ---------- projection : ndarray Matrix of projection for each polynomial degree. cell : int Index of cell. Returns ------- adapted_projection : ndarray Matrix of updated projection for each polynomial degree. """ cell_slope = self._set_cell_slope(projection, cell) is_good_cell = self._determine_modification(projection, cell, cell_slope) if is_good_cell: return projection[:, cell] adapted_projection = projection[:, cell].copy() for i in range(len(adapted_projection)): if i > self._erase_degree: adapted_projection[i] = 0 return adapted_projection def _determine_modification(self, projection, cell, cell_slope): """Determines whether limiting is applied. Parameters ---------- projection : ndarray Matrix of projection for each polynomial degree. cell : int Index of cell. cell_slope : float Slope of the given cell. Returns ------- bool Flag whether cell should be adjusted. """ forward_slope = (projection[0][cell+1] - projection[0][cell]) * (0.5**0.5) backward_slope = (projection[0][cell] - projection[0][cell-1]) * (0.5**0.5) return (forward_slope <= 0) & (backward_slope <= 0) \ & (cell_slope <= 0) \ | (forward_slope >= 0) & (backward_slope >= 0) & (cell_slope >= 0) @staticmethod def _set_cell_slope(projection, cell): """Calculates the slope of the cell. Parameters ---------- projection : ndarray Matrix of projection for each polynomial degree. cell : int Index of cell. Returns ------- float Slope of the given cell. """ slope = [] for current_cell in range(len(projection[0])): new_entry = sum( projection[degree][current_cell] * (degree+0.5)**0.5 for degree in range(1, len(projection))) slope.append(new_entry) return slope[cell] class ModifiedMinMod(MinMod): """Class for modified minmod limiting function. Sets projection for higher degrees to zero when forward backward, and cell slope values have not the same sign and cell slope is significantly high. Attributes ---------- cell_len : float Length of a cell in mesh. mod_factor : float Factor determining whether cell slope is significantly high enough for modification. Methods ------- get_name() Returns string of class name. Notes ----- Also called Cockburn-Shu limiter. """ def _reset(self, config): """Resets instance variables. Parameters ---------- config : dict Additional parameters for quadrature. """ super()._reset(config) # Unpack necessary configurations self._cell_len = config.pop('cell_len') self._mod_factor = config.pop('mod_factor', 0) def get_name(self): """Returns string of class name concatenated with the erase-degree.""" return self.__class__.__name__ + str(self._erase_degree) def _determine_modification(self, projection, cell, cell_slope): """Determines whether limiting is applied. Parameters ---------- projection : ndarray Matrix of projection for each polynomial degree. cell : int Index of cell. cell_slope : float Slope of the given cell. Returns ------- bool Flag whether cell should be adjusted. """ if abs(cell_slope) <= self._mod_factor*self._cell_len**2: return True return super()._determine_modification(projection, cell, cell_slope)