diff --git a/scripts/tcd/ANN_Data_Generator.py b/scripts/tcd/ANN_Data_Generator.py
index 07b88e21c1c2c9c5267d1b429f35f5e83e13b85b..33f7cf3ab1d7d70d2de2d9c8156b2a84f1c8ea57 100644
--- a/scripts/tcd/ANN_Data_Generator.py
+++ b/scripts/tcd/ANN_Data_Generator.py
@@ -8,7 +8,7 @@ import time
 import numpy as np
 
 from .DG_Approximation import do_initial_projection
-from .projection_utils import Mesh
+from .Mesh import Mesh
 from .Quadrature import Gauss
 from .Basis_Function import OrthonormalLegendre
 
diff --git a/scripts/tcd/DG_Approximation.py b/scripts/tcd/DG_Approximation.py
index 4a98383ffdb69d77fbd1a515bbf474403585ce19..0b07bb2771fd22c24dd1ce3dc709d4f5f885143d 100644
--- a/scripts/tcd/DG_Approximation.py
+++ b/scripts/tcd/DG_Approximation.py
@@ -16,7 +16,7 @@ from . import Quadrature
 from . import Update_Scheme
 from .Basis_Function import OrthonormalLegendre
 from .encoding_utils import encode_ndarray
-from .projection_utils import Mesh
+from .Mesh import Mesh
 
 x = Symbol('x')
 sns.set()
diff --git a/scripts/tcd/Mesh.py b/scripts/tcd/Mesh.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca15ed8ae2b055a637d61f92be882b6bf0fd047b
--- /dev/null
+++ b/scripts/tcd/Mesh.py
@@ -0,0 +1,152 @@
+# -*- coding: utf-8 -*-
+"""
+@author: Laura C. Kühle
+
+"""
+from __future__ import annotations
+import math
+import numpy as np
+from numpy import ndarray
+from typing import Tuple
+from functools import cache
+
+
+class Mesh:
+    """Class for mesh.
+
+    Each cell is characterized by its center.
+
+    Attributes
+    ----------
+    mode : str
+        Mode for mesh use. Either 'training' or 'evaluation'.
+    num_cells : int
+        Number of cells in the mesh (ghost cells notwithstanding). Usually
+        exponential of 2.
+    bounds : Tuple[float, float]
+        Left and right boundary of the mesh interval.
+    interval_len : float
+        Length of the mesh interval.
+    cell_len : float
+        Length of a mesh cell.
+    cells : ndarray
+        Array of cell centers in mesh.
+
+    Methods
+    -------
+    create_data_dict()
+        Return dictionary with data necessary to construct mesh.
+    random_stencil(stencil_len)
+        Return random stencil.
+
+    """
+
+    def __init__(self, num_cells: int, num_ghost_cells: int,
+                 left_bound: float, right_bound: float,
+                 training_data_mode: bool = False) -> None:
+        """Initialize Mesh.
+
+        Parameters
+        ----------
+        num_cells : int
+            Number of cells in the mesh (ghost cells notwithstanding). Has
+            to be an exponential of 2.
+        num_ghost_cells : int
+            Number of ghost cells on each side of the mesh.
+        left_bound : float
+            Left boundary of the mesh interval.
+        right_bound : float
+            Right boundary of the mesh interval.
+        training_data_mode : bool, optional
+            Flag indicating whether the mesh is used for training data
+            generation. Default: False.
+
+        Raises
+        ------
+        ValueError
+            If number of cells is not exponential of 2.
+
+        """
+        self._num_cells = num_cells
+        self._mode = 'training' if training_data_mode else 'evaluation'
+        if not training_data_mode:
+            if not math.log(self._num_cells, 2).is_integer():
+                raise ValueError('The number of cells in the mesh has to be '
+                                 'an exponential of 2')
+        self._num_ghost_cells = num_ghost_cells
+        self._left_bound = left_bound
+        self._right_bound = right_bound
+
+    @property
+    def mode(self) -> str:
+        """Return mode ('training' or 'evaluation')."""
+        return self._mode
+
+    @property
+    def num_cells(self) -> int:
+        """Return number of mesh cells."""
+        return self._num_cells
+
+    @property
+    def bounds(self) -> Tuple[float, float]:
+        """Return left and right boundary of the mesh interval."""
+        return self._left_bound, self._right_bound
+
+    @property
+    def interval_len(self) -> float:
+        """Return the length of the mesh interval."""
+        return self._right_bound - self._left_bound
+
+    @property
+    def cell_len(self) -> float:
+        """Return the length of a mesh cell."""
+        return self.interval_len/self.num_cells
+
+    @property
+    @cache
+    def cells(self) -> ndarray:
+        """Return the cell centers of the mesh (including ghost cells)."""
+        return np.arange(
+            self._left_bound - (self._num_ghost_cells*2-1)/2*self.cell_len,
+            self._right_bound + (self._num_ghost_cells*2+1)/2*self.cell_len,
+            self.cell_len)
+
+    @property
+    def non_ghost_cells(self) -> ndarray:
+        """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) -> dict:
+        """Return dictionary with data necessary to construct mesh."""
+        return {'num_cells': self._num_cells,
+                'left_bound': self._left_bound,
+                'right_bound': self._right_bound,
+                'num_ghost_cells': self._num_ghost_cells}
+
+    def random_stencil(self, stencil_len: 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 mesh spacing to be within interval if necessary
+        mesh_spacing = self.cell_len
+        max_spacing = 2/stencil_len*min(point-self._left_bound,
+                                        self._right_bound-point)
+        while mesh_spacing > max_spacing:
+            mesh_spacing /= 2
+
+        # Return new mesh instance
+        return Mesh(left_bound=point - stencil_len/2 * mesh_spacing,
+                    right_bound=point + stencil_len/2 * mesh_spacing,
+                    num_cells=stencil_len, num_ghost_cells=2,
+                    training_data_mode=True)
\ No newline at end of file
diff --git a/scripts/tcd/Plotting.py b/scripts/tcd/Plotting.py
index 43dcaa3b725da8afb6f48b8073ca4352b8646374..908292df7a815925c4275dfb74d8ddf032c77a69 100644
--- a/scripts/tcd/Plotting.py
+++ b/scripts/tcd/Plotting.py
@@ -18,7 +18,8 @@ from .Quadrature import Quadrature
 from .Initial_Condition import InitialCondition
 from .Basis_Function import Basis, OrthonormalLegendre
 from .projection_utils import calculate_exact_solution,\
-    calculate_approximate_solution, Mesh
+    calculate_approximate_solution
+from .Mesh import Mesh
 from .encoding_utils import decode_ndarray
 
 
diff --git a/scripts/tcd/Troubled_Cell_Detector.py b/scripts/tcd/Troubled_Cell_Detector.py
index 52f4cc2b4c475f8d1c90961fdb06e2a1391efe68..c84e2820407940cf59666efde8bba57928bee1f7 100644
--- a/scripts/tcd/Troubled_Cell_Detector.py
+++ b/scripts/tcd/Troubled_Cell_Detector.py
@@ -8,7 +8,7 @@ import numpy as np
 import torch
 
 from . import ANN_Model
-from .projection_utils import Mesh
+from .Mesh import Mesh
 
 
 class TroubledCellDetector(ABC):
diff --git a/scripts/tcd/projection_utils.py b/scripts/tcd/projection_utils.py
index 4f4b099eaf3bba5044c219830a1f8a8bfd338ed4..c6b710b2e98e8df12190a401d2342b910180b17b 100644
--- a/scripts/tcd/projection_utils.py
+++ b/scripts/tcd/projection_utils.py
@@ -4,14 +4,12 @@
 
 """
 
-from __future__ import annotations
-from functools import cache
 from typing import Tuple
-import math
 import numpy as np
 from numpy import ndarray
 from sympy import Symbol
 
+from .Mesh import Mesh
 from .Quadrature import Quadrature
 from .Initial_Condition import InitialCondition
 
@@ -19,147 +17,6 @@ from .Initial_Condition import InitialCondition
 x = Symbol('x')
 
 
-class Mesh:
-    """Class for mesh.
-
-    Each cell is characterized by its center.
-
-    Attributes
-    ----------
-    mode : str
-        Mode for mesh use. Either 'training' or 'evaluation'.
-    num_cells : int
-        Number of cells in the mesh (ghost cells notwithstanding). Usually
-        exponential of 2.
-    bounds : Tuple[float, float]
-        Left and right boundary of the mesh interval.
-    interval_len : float
-        Length of the mesh interval.
-    cell_len : float
-        Length of a mesh cell.
-    cells : ndarray
-        Array of cell centers in mesh.
-
-    Methods
-    -------
-    create_data_dict()
-        Return dictionary with data necessary to construct mesh.
-    random_stencil(stencil_len)
-        Return random stencil.
-
-    """
-
-    def __init__(self, num_cells: int, num_ghost_cells: int,
-                 left_bound: float, right_bound: float,
-                 training_data_mode: bool = False) -> None:
-        """Initialize Mesh.
-
-        Parameters
-        ----------
-        num_cells : int
-            Number of cells in the mesh (ghost cells notwithstanding). Has
-            to be an exponential of 2.
-        num_ghost_cells : int
-            Number of ghost cells on each side of the mesh.
-        left_bound : float
-            Left boundary of the mesh interval.
-        right_bound : float
-            Right boundary of the mesh interval.
-        training_data_mode : bool, optional
-            Flag indicating whether the mesh is used for training data
-            generation. Default: False.
-
-        Raises
-        ------
-        ValueError
-            If number of cells is not exponential of 2.
-
-        """
-        self._num_cells = num_cells
-        self._mode = 'training' if training_data_mode else 'evaluation'
-        if not training_data_mode:
-            if not math.log(self._num_cells, 2).is_integer():
-                raise ValueError('The number of cells in the mesh has to be '
-                                 'an exponential of 2')
-        self._num_ghost_cells = num_ghost_cells
-        self._left_bound = left_bound
-        self._right_bound = right_bound
-
-    @property
-    def mode(self) -> str:
-        """Return mode ('training' or 'evaluation')."""
-        return self._mode
-
-    @property
-    def num_cells(self) -> int:
-        """Return number of mesh cells."""
-        return self._num_cells
-
-    @property
-    def bounds(self) -> Tuple[float, float]:
-        """Return left and right boundary of the mesh interval."""
-        return self._left_bound, self._right_bound
-
-    @property
-    def interval_len(self) -> float:
-        """Return the length of the mesh interval."""
-        return self._right_bound - self._left_bound
-
-    @property
-    def cell_len(self) -> float:
-        """Return the length of a mesh cell."""
-        return self.interval_len/self.num_cells
-
-    @property
-    @cache
-    def cells(self) -> ndarray:
-        """Return the cell centers of the mesh (including ghost cells)."""
-        return np.arange(
-            self._left_bound - (self._num_ghost_cells*2-1)/2*self.cell_len,
-            self._right_bound + (self._num_ghost_cells*2+1)/2*self.cell_len,
-            self.cell_len)
-
-    @property
-    def non_ghost_cells(self) -> ndarray:
-        """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) -> dict:
-        """Return dictionary with data necessary to construct mesh."""
-        return {'num_cells': self._num_cells,
-                'left_bound': self._left_bound,
-                'right_bound': self._right_bound,
-                'num_ghost_cells': self._num_ghost_cells}
-
-    def random_stencil(self, stencil_len: 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 mesh spacing to be within interval if necessary
-        mesh_spacing = self.cell_len
-        max_spacing = 2/stencil_len*min(point-self._left_bound,
-                                        self._right_bound-point)
-        while mesh_spacing > max_spacing:
-            mesh_spacing /= 2
-
-        # Return new mesh instance
-        return Mesh(left_bound=point - stencil_len/2 * mesh_spacing,
-                    right_bound=point + stencil_len/2 * mesh_spacing,
-                    num_cells=stencil_len, num_ghost_cells=2,
-                    training_data_mode=True)
-
-
 def calculate_approximate_solution(
         projection: ndarray, points: ndarray, polynomial_degree: int,
         basis: ndarray) -> ndarray: