Skip to content
Snippets Groups Projects
Commit e036e917 authored by Laura Christine Kühle's avatar Laura Christine Kühle
Browse files

Enforced periodic boundary condition for projection with decorator.

parent d05acbc2
Branches
No related tags found
No related merge requests found
...@@ -24,7 +24,7 @@ TODO: Discuss how wavelet details should be plotted ...@@ -24,7 +24,7 @@ TODO: Discuss how wavelet details should be plotted
Urgent: Urgent:
TODO: Refactor Boxplot class -> Done TODO: Refactor Boxplot class -> Done
TODO: Enforce boundary condition with decorator TODO: Enforce periodic boundary condition for projection with decorator -> Done
TODO: Enforce Boxplot bounds with decorator TODO: Enforce Boxplot bounds with decorator
TODO: Enforce Boxplot folds with decorator TODO: Enforce Boxplot folds with decorator
TODO: Enforce boundary for initial condition in exact solution only TODO: Enforce boundary for initial condition in exact solution only
......
# -*- coding: utf-8 -*-
"""
@author: Laura C. Kühle
"""
# from typing import Tuple
# from abc import ABC, abstractmethod
# import numpy as np
from numpy import ndarray
# from .Basis_Function import Basis
# from .Initial_Condition import InitialCondition
# from .Mesh import Mesh
# from .projection_utils import do_initial_projection
# from .Quadrature import Quadrature
def periodic_boundary(projection: ndarray, num_ghost_cells: int) -> ndarray:
"""Enforce boundary condition.
Adjust ghost cells to ensure periodic boundary condition.
Parameters
----------
projection : ndarray
Matrix of projection for each polynomial degree.
num_ghost_cells : int
Number of ghost cells to be adjusted.
Returns
-------
projection : ndarray
Matrix of projection for each polynomial degree.
"""
projection[:, :num_ghost_cells] = \
projection[:, -2 * num_ghost_cells:-num_ghost_cells]
projection[:, -num_ghost_cells:] = \
projection[:, num_ghost_cells:2 * num_ghost_cells]
return projection
def dirichlet_boundary(projection: ndarray, num_ghost_cells: int) -> ndarray:
"""Enforce boundary condition.
Adjust ghost cells to ensure Dirichlet boundary condition.
Parameters
----------
projection : ndarray
Matrix of projection for each polynomial degree.
num_ghost_cells : int
Number of ghost cells to be adjusted.
Returns
-------
projection : ndarray
Matrix of projection for each polynomial degree.
"""
pass
def enforce_boundary(num_ghost_cells=None):
def _enforce_boundary(func):
def boundary(self, *args, **kwargs):
projection = func(self, *args, **kwargs)
if self._mesh.boundary == 'periodic':
return periodic_boundary(
projection=projection, num_ghost_cells=num_ghost_cells
if num_ghost_cells is not None
else self._mesh.num_ghost_cells)
else:
raise Exception('Not implemented!')
return boundary
return _enforce_boundary
...@@ -9,6 +9,7 @@ import numpy as np ...@@ -9,6 +9,7 @@ import numpy as np
from numpy import ndarray from numpy import ndarray
from .Basis_Function import Basis from .Basis_Function import Basis
from .Boundary_Condition import enforce_boundary
from .Initial_Condition import InitialCondition from .Initial_Condition import InitialCondition
from .Mesh import Mesh from .Mesh import Mesh
from .projection_utils import do_initial_projection from .projection_utils import do_initial_projection
...@@ -26,8 +27,6 @@ class Equation(ABC): ...@@ -26,8 +27,6 @@ class Equation(ABC):
Update time step. Update time step.
solve_exactly(mesh) solve_exactly(mesh)
Calculate exact solution. Calculate exact solution.
enforce_boundary_condition(projection)
Enforce boundary condition.
update_right_hand_side(projection) update_right_hand_side(projection)
Update right-hand side. Update right-hand side.
""" """
...@@ -93,6 +92,7 @@ class Equation(ABC): ...@@ -93,6 +92,7 @@ class Equation(ABC):
return abs(self._cfl_number * self._mesh.cell_len / self._wave_speed) return abs(self._cfl_number * self._mesh.cell_len / self._wave_speed)
@abstractmethod @abstractmethod
@enforce_boundary()
def _initialize_projection(self) -> ndarray: def _initialize_projection(self) -> ndarray:
"""Initialize projection.""" """Initialize projection."""
pass pass
...@@ -138,25 +138,7 @@ class Equation(ABC): ...@@ -138,25 +138,7 @@ class Equation(ABC):
pass pass
@abstractmethod @abstractmethod
def enforce_boundary_condition(self, projection: ndarray) -> ndarray: @enforce_boundary()
"""Enforce boundary condition.
Adjust ghost cells to ensure periodic boundary condition.
Parameters
----------
projection : ndarray
Matrix of projection for each polynomial degree.
Returns
-------
projection : ndarray
Matrix of projection for each polynomial degree.
"""
pass
@abstractmethod
def update_right_hand_side(self, projection: ndarray) -> ndarray: def update_right_hand_side(self, projection: ndarray) -> ndarray:
"""Update right-hand side. """Update right-hand side.
...@@ -188,8 +170,6 @@ class LinearAdvection(Equation): ...@@ -188,8 +170,6 @@ class LinearAdvection(Equation):
------- -------
update_right_hand_side(projection) update_right_hand_side(projection)
Update right-hand side. Update right-hand side.
enforce_boundary_condition(projection)
Enforce boundary condition.
Notes Notes
----- -----
...@@ -222,6 +202,7 @@ class LinearAdvection(Equation): ...@@ -222,6 +202,7 @@ class LinearAdvection(Equation):
else np.fromfunction(lambda i, j: (-1.0)**j, matrix_shape) else np.fromfunction(lambda i, j: (-1.0)**j, matrix_shape)
self._flux_matrix = matrix * degree_matrix self._flux_matrix = matrix * degree_matrix
@enforce_boundary()
def _initialize_projection(self) -> ndarray: def _initialize_projection(self) -> ndarray:
"""Initialize projection.""" """Initialize projection."""
return do_initial_projection(init_cond=self._init_cond, return do_initial_projection(init_cond=self._init_cond,
...@@ -283,28 +264,7 @@ class LinearAdvection(Equation): ...@@ -283,28 +264,7 @@ class LinearAdvection(Equation):
return grid, exact return grid, exact
def enforce_boundary_condition(self, projection: ndarray) -> ndarray: @enforce_boundary()
"""Enforce boundary condition.
Adjust ghost cells to ensure periodic boundary condition.
Parameters
----------
projection : ndarray
Matrix of projection for each polynomial degree.
Returns
-------
projection : ndarray
Matrix of projection for each polynomial degree.
"""
projection[:, :self._mesh.num_ghost_cells] = projection[
:, -2*self._mesh.num_ghost_cells:-self._mesh.num_ghost_cells]
projection[:, -self._mesh.num_ghost_cells:] = projection[
:, self._mesh.num_ghost_cells:2*self._mesh.num_ghost_cells]
return projection
def update_right_hand_side(self, projection: ndarray) -> ndarray: def update_right_hand_side(self, projection: ndarray) -> ndarray:
"""Update right-hand side. """Update right-hand side.
...@@ -338,10 +298,4 @@ class LinearAdvection(Equation): ...@@ -338,10 +298,4 @@ class LinearAdvection(Equation):
projection[:, self._mesh.num_ghost_cells: projection[:, self._mesh.num_ghost_cells:
-self._mesh.num_ghost_cells]) -self._mesh.num_ghost_cells])
# Set ghost cells to respective value
right_hand_side[:, :self._mesh.num_ghost_cells] = right_hand_side[
:, -2*self._mesh.num_ghost_cells:-self._mesh.num_ghost_cells]
right_hand_side[:, -self._mesh.num_ghost_cells:] = right_hand_side[
:, self._mesh.num_ghost_cells:2*self._mesh.num_ghost_cells]
return right_hand_side return right_hand_side
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
import numpy as np import numpy as np
from .Boundary_Condition import enforce_boundary
class Limiter(ABC): class Limiter(ABC):
"""Abstract class for limiting function. """Abstract class for limiting function.
...@@ -50,6 +52,7 @@ class Limiter(ABC): ...@@ -50,6 +52,7 @@ class Limiter(ABC):
return self.__class__.__name__ return self.__class__.__name__
@abstractmethod @abstractmethod
@enforce_boundary()
def apply(self, projection, cells): def apply(self, projection, cells):
"""Applies limiting to cells. """Applies limiting to cells.
...@@ -80,6 +83,7 @@ class NoLimiter(Limiter): ...@@ -80,6 +83,7 @@ class NoLimiter(Limiter):
Applies no limiting to cells. Applies no limiting to cells.
""" """
@enforce_boundary()
def apply(self, projection, cells): def apply(self, projection, cells):
"""Returns projection without limiting.""" """Returns projection without limiting."""
return projection return projection
...@@ -121,6 +125,7 @@ class MinMod(Limiter): ...@@ -121,6 +125,7 @@ class MinMod(Limiter):
"""Returns string of class name concatenated with the erase-degree.""" """Returns string of class name concatenated with the erase-degree."""
return self.__class__.__name__ + str(self._erase_degree) return self.__class__.__name__ + str(self._erase_degree)
@enforce_boundary()
def apply(self, projection, cells): def apply(self, projection, cells):
"""Applies limiting to cells. """Applies limiting to cells.
......
...@@ -77,6 +77,7 @@ class Mesh: ...@@ -77,6 +77,7 @@ class Mesh:
'an exponential of 2') 'an exponential of 2')
self._left_bound = left_bound self._left_bound = left_bound
self._right_bound = right_bound self._right_bound = right_bound
self.boundary = 'periodic'
@property @property
def mode(self) -> str: def mode(self) -> str:
......
...@@ -150,23 +150,17 @@ class SSPRK3(UpdateScheme): ...@@ -150,23 +150,17 @@ class SSPRK3(UpdateScheme):
current_projection = self._apply_first_step(original_projection, current_projection = self._apply_first_step(original_projection,
cfl_number) cfl_number)
current_projection, __ = self._apply_limiter(current_projection) current_projection, __ = self._apply_limiter(current_projection)
current_projection = self._equation.enforce_boundary_condition(
current_projection)
current_projection = self._apply_second_step(original_projection, current_projection = self._apply_second_step(original_projection,
current_projection, current_projection,
cfl_number) cfl_number)
current_projection, __ = self._apply_limiter(current_projection) current_projection, __ = self._apply_limiter(current_projection)
current_projection = self._equation.enforce_boundary_condition(
current_projection)
current_projection = self._apply_third_step(original_projection, current_projection = self._apply_third_step(original_projection,
current_projection, current_projection,
cfl_number) cfl_number)
current_projection, troubled_cells = self._apply_limiter( current_projection, troubled_cells = self._apply_limiter(
current_projection) current_projection)
current_projection = self._equation.enforce_boundary_condition(
current_projection)
return current_projection, troubled_cells return current_projection, troubled_cells
......
...@@ -140,10 +140,4 @@ def do_initial_projection(init_cond, mesh, basis, quadrature, ...@@ -140,10 +140,4 @@ def do_initial_projection(init_cond, mesh, basis, quadrature,
output_matrix.shape[-1]-mesh.num_ghost_cells] = \ output_matrix.shape[-1]-mesh.num_ghost_cells] = \
(basis_matrix * quadrature.weights) @ init_matrix (basis_matrix * quadrature.weights) @ init_matrix
# Set ghost cells
output_matrix[:, :mesh.num_ghost_cells] = \
output_matrix[:, -2*mesh.num_ghost_cells:-mesh.num_ghost_cells]
output_matrix[:, output_matrix.shape[-1]-mesh.num_ghost_cells:] = \
output_matrix[:, mesh.num_ghost_cells:2*mesh.num_ghost_cells]
return output_matrix return output_matrix
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment