Repository: esa/NIDN (language: python)

Issue:
Get first runnable version of FDTD
# Feature
## Desired Behavior / Functionality
Add any missing parts to get be able to call compute_spectrum 

## What Needs to Be Done
- Add the stuff
- Set up a test to run compute spectrum once and check if the results remain consistent

## How Can It Be Tested
 New test



Discussion / hints:

Fix patch:
diff --git a/nidn/__init__.py b/nidn/__init__.py
index 064da5b..e2afbcf 100644
--- a/nidn/__init__.py
+++ b/nidn/__init__.py
@@ -20,7 +20,7 @@
 from .training.save_run import save_run
 from .trcwa.compute_target_frequencies import compute_target_frequencies
 from .trcwa.get_frequency_points import get_frequency_points
-from .trcwa.compute_spectrum import compute_spectrum
+from .utils.compute_spectrum import compute_spectrum
 from .utils.convert_units import freq_to_wl, wl_to_phys_wl, phys_freq_to_phys_wl
 from .utils.fix_random_seeds import fix_random_seeds
 from .utils.load_default_cfg import load_default_cfg
diff --git a/nidn/fdtd/__init__.py b/nidn/fdtd/__init__.py
new file mode 100644
index 0000000..43de209
--- /dev/null
+++ b/nidn/fdtd/__init__.py
@@ -0,0 +1,14 @@
+""" Python 3D FDTD Simulator """
+
+__author__ = "Floris laporte"
+__version__ = "0.2.4"
+
+from .grid import Grid
+from .sources import PointSource, LineSource, PlaneSource
+from .detectors import LineDetector, BlockDetector, CurrentDetector
+from .objects import Object, AbsorbingObject, AnisotropicObject
+from .boundaries import PeriodicBoundary, PML
+from .backend import backend
+from .backend import set_backend
+from .fourier import FrequencyRoutines
+from .visualization import dB_map_2D, plot_detection
diff --git a/nidn/fdtd/backend.py b/nidn/fdtd/backend.py
new file mode 100644
index 0000000..290030d
--- /dev/null
+++ b/nidn/fdtd/backend.py
@@ -0,0 +1,301 @@
+""" Selects the backend for the fdtd-package.
+
+The `fdtd` library allows to choose a backend. The ``numpy`` backend is the
+default one, but there are also several additional PyTorch backends:
+
+    - ``numpy`` (defaults to float64 arrays)
+    - ``torch`` (defaults to float64 tensors)
+    - ``torch.float32``
+    - ``torch.float64``
+    - ``torch.cuda`` (defaults to float64 tensors)
+    - ``torch.cuda.float32``
+    - ``torch.cuda.float64``
+
+For example, this is how to choose the `"torch"` backend: ::
+
+    fdtd.set_backend("torch")
+
+In general, the ``numpy`` backend is preferred for standard CPU calculations
+with `"float64"` precision. In general, ``float64`` precision is always
+preferred over ``float32`` for FDTD simulations, however, ``float32`` might
+give a significant performance boost.
+
+The ``cuda`` backends are only available for computers with a GPU.
+
+"""
+
+## Imports
+
+# Numpy Backend
+import numpy  # numpy has to be present
+from functools import wraps
+
+# used only by test runner.
+# default must be idx 0.
+backend_names = [
+    dict(backends="numpy"),
+    dict(backends="torch.float32"),
+    dict(backends="torch.float64"),
+    dict(backends="torch.cuda.float32"),
+    dict(backends="torch.cuda.float64"),
+]
+
+numpy_float_dtypes = {
+    getattr(numpy, "float_", numpy.float64),
+    getattr(numpy, "float16", numpy.float64),
+    getattr(numpy, "float32", numpy.float64),
+    getattr(numpy, "float64", numpy.float64),
+    getattr(numpy, "float128", numpy.float64),
+}
+
+
+# Torch Backends (and flags)
+try:
+    import torch
+
+    torch.set_default_dtype(torch.float64)  # we need more precision for FDTD
+    try:  # we don't need gradients (for now)
+        torch._C.set_grad_enabled(False)  # type: ignore
+    except AttributeError:
+        torch._C._set_grad_enabled(False)
+    TORCH_AVAILABLE = True
+    TORCH_CUDA_AVAILABLE = torch.cuda.is_available()
+except ImportError:
+    TORCH_AVAILABLE = False
+    TORCH_CUDA_AVAILABLE = False
+
+
+# Base Class
+class Backend:
+    """Backend Base Class"""
+
+    def __repr__(self):
+        return self.__class__.__name__
+
+
+def _replace_float(func):
+    """replace the default dtype a function is called with"""
+
+    @wraps(func)
+    def new_func(self, *args, **kwargs):
+        result = func(*args, **kwargs)
+        if result.dtype in numpy_float_dtypes:
+            result = numpy.asarray(result, dtype=self.float)
+        return result
+
+    return new_func
+
+
+# Torch Backend
+if TORCH_AVAILABLE:
+    import torch
+
+    class TorchBackend(Backend):
+        """Torch Backend"""
+
+        # types
+        int = torch.int64
+        """ integer type for array"""
+
+        float = torch.get_default_dtype()
+        """ floating type for array """
+
+        # methods
+        asarray = staticmethod(torch.as_tensor)
+        """ create an array """
+
+        exp = staticmethod(torch.exp)
+        """ exponential of all elements in array """
+
+        sin = staticmethod(torch.sin)
+        """ sine of all elements in array """
+
+        cos = staticmethod(torch.cos)
+        """ cosine of all elements in array """
+
+        sum = staticmethod(torch.sum)
+        """ sum elements in array """
+
+        max = staticmethod(torch.max)
+        """ max element in array """
+
+        stack = staticmethod(torch.stack)
+        """ stack multiple arrays """
+
+        @staticmethod
+        def transpose(arr, axes=None):
+            """transpose array by flipping two dimensions"""
+            if axes is None:
+                axes = tuple(range(len(arr.shape) - 1, -1, -1))
+            return arr.permute(*axes)
+
+        squeeze = staticmethod(torch.squeeze)
+        """ remove dim-1 dimensions """
+
+        broadcast_arrays = staticmethod(torch.broadcast_tensors)
+        """ broadcast arrays """
+
+        broadcast_to = staticmethod(torch.broadcast_to)
+        """ broadcast array into shape """
+
+        reshape = staticmethod(torch.reshape)
+        """ reshape array into given shape """
+
+        bmm = staticmethod(torch.bmm)
+        """ batch matrix multiply two arrays """
+
+        @staticmethod
+        def is_array(arr):
+            """check if an object is an array"""
+            # is this a reasonable implemenation?
+            return isinstance(arr, numpy.ndarray) or torch.is_tensor(arr)
+
+        def array(self, arr, dtype=None):
+            """create an array from an array-like sequence"""
+            if dtype is None:
+                dtype = torch.get_default_dtype()
+            if torch.is_tensor(arr):
+                return arr.clone().to(device="cpu", dtype=dtype)
+            return torch.tensor(arr, device="cpu", dtype=dtype)
+
+        # constructors
+        ones = staticmethod(torch.ones)
+        """ create an array filled with ones """
+
+        zeros = staticmethod(torch.zeros)
+        """ create an array filled with zeros """
+
+        def linspace(self, start, stop, num=50, endpoint=True):
+            """create a linearly spaced array between two points"""
+            delta = (stop - start) / float(num - float(endpoint))
+            if not delta:
+                return self.array([start] * num)
+            return torch.arange(start, stop + 0.5 * float(endpoint) * delta, delta)
+
+        arange = staticmethod(torch.arange)
+        """ create a range of values """
+
+        pad = staticmethod(torch.nn.functional.pad)  # type: ignore
+
+        fftfreq = staticmethod(numpy.fft.fftfreq)
+
+        fft = staticmethod(torch.fft)  # type: ignore
+
+        divide = staticmethod(torch.div)
+
+        exp = staticmethod(torch.exp)
+        # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        # The same warning applies here.
+        # <3 <3 <3 <3
+
+        def numpy(self, arr):
+            """convert the array to numpy array"""
+            if torch.is_tensor(arr):
+                return arr.numpy()
+            else:
+                return numpy.asarray(arr)
+
+    # Torch Cuda Backend
+    if TORCH_CUDA_AVAILABLE:
+
+        class TorchCudaBackend(TorchBackend):
+            """Torch Cuda Backend"""
+
+            def ones(self, shape):
+                """create an array filled with ones"""
+                return torch.ones(shape, device="cuda")
+
+            def zeros(self, shape):
+                """create an array filled with zeros"""
+                return torch.zeros(shape, device="cuda")
+
+            def array(self, arr, dtype=None):
+                """create an array from an array-like sequence"""
+                if dtype is None:
+                    dtype = torch.get_default_dtype()
+                if torch.is_tensor(arr):
+                    return arr.clone().to(device="cuda", dtype=dtype)
+                return torch.tensor(arr, device="cuda", dtype=dtype)
+
+            # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+            # The same warning applies here.
+            def numpy(self, arr):
+                """convert the array to numpy array"""
+                if torch.is_tensor(arr):
+                    return arr.cpu().numpy()
+                else:
+                    return numpy.asarray(arr)
+
+            def linspace(self, start, stop, num=50, endpoint=True):
+                """convert a linearly spaced interval of values"""
+                delta = (stop - start) / float(num - float(endpoint))
+                if not delta:
+                    return self.array([start] * num)
+                return torch.arange(
+                    start, stop + 0.5 * float(endpoint) * delta, delta, device="cuda"
+                )
+
+
+## Default Backend
+# this backend object will be used for all array/tensor operations.
+# the backend is changed by changing the class of the backend
+# using the "set_backend" function. This "monkeypatch" will replace all the methods
+# of the backend object by the methods supplied by the new class.
+backend = TorchBackend()
+
+
+## Set backend
+def set_backend(name: str):
+    """Set the backend for the FDTD simulations
+
+    This function monkeypatches the backend object by changing its class.
+    This way, all methods of the backend object will be replaced.
+
+    Args:
+        name: name of the backend. Allowed backend names:
+            - ``torch`` (defaults to float64 tensors)
+            - ``torch.float16``
+            - ``torch.float32``
+            - ``torch.float64``
+            - ``torch.cuda`` (defaults to float64 tensors)
+            - ``torch.cuda.float16``
+            - ``torch.cuda.float32``
+            - ``torch.cuda.float64``
+
+    """
+    # perform checks
+    if name.startswith("torch") and not TORCH_AVAILABLE:
+        raise RuntimeError("Torch backend is not available. Is PyTorch installed?")
+    if name.startswith("torch.cuda") and not TORCH_CUDA_AVAILABLE:
+        raise RuntimeError(
+            "Torch cuda backend is not available.\n"
+            "Do you have a GPU on your computer?\n"
+            "Is PyTorch with cuda support installed?"
+        )
+
+    if name.count(".") == 0:
+        dtype, device = "float64", "cpu"
+    elif name.count(".") == 1:
+        name, dtype = name.split(".")
+        if dtype == "cuda":
+            device, dtype = "cuda", "float64"
+        else:
+            device = "cpu"
+    elif name.count(".") == 2:
+        name, device, dtype = name.split(".")
+    else:
+        raise ValueError(f"Unknown backend '{name}'")
+
+    if name == "torch":
+        if device == "cpu":
+            backend.__class__ = TorchBackend
+            backend.float = getattr(torch, dtype)
+        elif device == "cuda":
+            backend.__class__ = TorchCudaBackend
+            backend.float = getattr(torch, dtype)
+        else:
+            raise ValueError(
+                "Unknown device '{device}'. Available devices: 'cpu', 'cuda'"
+            )
+    else:
+        raise ValueError("Unknown backend '{name}'. Available backends: 'torch'")
diff --git a/nidn/fdtd/boundaries.py b/nidn/fdtd/boundaries.py
new file mode 100644
index 0000000..5d36fb7
--- /dev/null
+++ b/nidn/fdtd/boundaries.py
@@ -0,0 +1,649 @@
+""" Boundaries for the FDTD Grid.
+
+Available Boundaries:
+
+ - PeriodicBoundary
+ - PML
+
+"""
+## Imports
+
+# typing
+from .typing_ import Tensorlike, ListOrSlice, IntOrSlice
+
+# relative
+from .grid import Grid
+from .backend import backend as bd
+
+## Boundary Conditions [base class]
+class Boundary:
+    """an FDTD Boundary [base class]"""
+
+    def __init__(self, name: str = None):
+        """Create a boundary
+
+        Args:
+            name: name of the boundary
+        """
+        self.grid = None  # will be registered later
+        self.name = name
+
+    def _register_grid(
+        self, grid: Grid, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ):
+        """Register a grid to the boundary
+
+        Args:
+            grid: the grid to register the boundary to
+            x: the x-location of the boundary
+            y: the y-location of the boundary
+            z: the z-location of the boundary
+
+        Note:
+            This is a helper method. To register the boundary to the grid,
+            index the grid and assign to it:
+            grid[0,:,:] = Boundary(name="boundary_name")
+        """
+        self.grid = grid
+        self.grid.boundaries.append(self)
+        self.x = self._handle_slice(x)
+        self.y = self._handle_slice(y)
+        self.z = self._handle_slice(z)
+
+        # Put into unique_name_check function?
+        if self.name is not None:
+            if not hasattr(grid, self.name):
+                setattr(grid, self.name, self)
+            else:
+                raise ValueError(
+                    f"The grid already has an attribute with name {self.name}"
+                )
+
+    def _handle_slice(self, s: ListOrSlice) -> IntOrSlice:
+        if isinstance(s, list):
+            if len(s) > 1:
+                raise ValueError(
+                    "Use slices or single numbers to index the grid for a boundary"
+                )
+            return s[0]
+        if isinstance(s, slice):
+            if (
+                s.start is not None
+                and s.stop is not None
+                and (s.start == s.stop or abs(s.start - s.stop) == 1)
+            ):
+                return s.start
+            return s
+        raise ValueError("Invalid grid indexing used for boundary")
+
+    def update_phi_E(self):
+        """Update convolution [phi_E]
+
+        Note:
+            this method is called *before* the electric field is updated
+        """
+
+    def update_phi_H(self):
+        """Update convolution [phi_H]
+
+        Note:
+            this method is called *before* the magnetic field is updated
+        """
+
+    def update_E(self):
+        """Update electric field of the grid
+
+        Note:
+            this method is called *after* the grid fields are updated
+        """
+
+    def update_H(self):
+        """Update magnetic field of the grid
+
+        Note:
+            this method is called *after* the grid fields are updated
+        """
+
+    def __repr__(self):
+        return f"PML(name={repr(self.name)})"
+
+    def __str__(self):
+        s = "    " + repr(self) + "\n"
+
+        def _handle_slice(s):
+            return (
+                str(s)
+                .replace("slice(", "")
+                .replace(")", "")
+                .replace(", ", ":")
+                .replace("None", "")
+            )
+
+        x = _handle_slice(self.x)
+        y = _handle_slice(self.y)
+        z = _handle_slice(self.z)
+        s += f"        @ x={x}, y={y}, z={z}".replace(":,", ",")
+        if s[-1] == ":":
+            s = s[:-1]
+        return s + "\n"
+
+
+## Periodic Boundaries
+class PeriodicBoundary(Boundary):
+    """An FDTD Periodic Boundary
+
+    Note:
+        Registering a periodic boundary to the grid will change the periodic
+        boundary in one of its subclasses: ``_PeriodicBoundaryX``,
+        ``_PeriodicBoundaryY`` or ``_PeriodicBoundaryY``, depending on the
+        position in the grid.
+    """
+
+    def _register_grid(
+        self, grid: Grid, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ):
+        super()._register_grid(grid=grid, x=x, y=y, z=z)
+
+        if self.x == 0 or self.x == -1:
+            self.__class__ = _PeriodicBoundaryX  # subclass of PeriodicBoundary
+            if hasattr(grid, "_xlow_boundary") or hasattr(grid, "_xhigh_boundary"):
+                raise AttributeError("grid already has an xlow/xhigh boundary!")
+            setattr(grid, "_xlow_boundary", self)
+            setattr(grid, "_xhigh_boundary", self)
+        elif self.y == 0 or self.y == -1:
+            self.__class__ = _PeriodicBoundaryY  # subclass of PeriodicBoundary
+            if hasattr(grid, "_ylow_boundary") or hasattr(grid, "_yhigh_boundary"):
+                raise AttributeError("grid already has an ylow/yhigh boundary!")
+            setattr(grid, "_ylow_boundary", self)
+            setattr(grid, "_yhigh_boundary", self)
+        elif self.z == 0 or self.z == -1:
+            self.__class__ = _PeriodicBoundaryZ  # subclass of PeriodicBoundary
+            if hasattr(grid, "_zlow_boundary") or hasattr(grid, "_zhigh_boundary"):
+                raise AttributeError("grid already has an zlow/zhigh boundary!")
+            setattr(grid, "_zlow_boundary", self)
+            setattr(grid, "_zhigh_boundary", self)
+        else:
+            raise IndexError(
+                "A periodic boundary should be placed at the boundary of the "
+                "grid using a single index (either 0 or -1)"
+            )
+
+
+# Periodic Boundaries in the X-direction
+class _PeriodicBoundaryX(PeriodicBoundary):
+    def update_E(self):
+        """Update electric field such that periodic boundary conditions in the
+        X-direction apply"""
+        self.grid.E[0, :, :, :] = self.grid.E[-1, :, :, :]
+
+    def update_H(self):
+        """Update magnetic field such that periodic boundary conditions in the
+        X-directions apply"""
+        self.grid.H[-1, :, :, :] = self.grid.H[0, :, :, :]
+
+
+# Periodic Boundaries in the Y-direction
+class _PeriodicBoundaryY(PeriodicBoundary):
+    def update_E(self):
+        """Update electric field such that periodic boundary conditions in the
+        Y-direction apply"""
+        self.grid.E[:, 0, :, :] = self.grid.E[:, -1, :, :]
+
+    def update_H(self):
+        """Update magnetic field such that periodic boundary conditions in the
+        Y-direction apply"""
+        self.grid.H[:, -1, :, :] = self.grid.H[:, 0, :, :]
+
+
+# Periodic Boundaries in the Z-direction
+class _PeriodicBoundaryZ(PeriodicBoundary):
+    def update_E(self):
+        """Update electric field such that periodic boundary conditions in the
+        Z-direction apply"""
+        self.grid.E[:, :, 0, :] = self.grid.E[:, :, -1, :]
+
+    def update_H(self):
+        """Update magnetic field such that periodic boundary conditions in the
+        Z-direction apply"""
+        self.grid.H[:, :, -1, :] = self.grid.H[:, :, 0, :]
+
+
+## Perfectly Matched Layer (PML)
+
+
+class PML(Boundary):
+    """A perfectly matched layer (PML)
+
+    a PML is an impedence-matched area at the boundary of the grid for which
+    all fields incident perpendicular to the area are absorbed without
+    reflection.
+
+    Note:
+        Registering a PML to the grid will monkeypatch the PML to become one of
+        its subclasses: ``_PMLXlow``, ``_PMLYlow`` or ``_PMLZlow``,
+        ``_PMLXhigh``, ``_PMLYhigh``, ``_PMLZhigh`` depending on the position
+        in the grid.
+    """
+
+    def __init__(self, a: float = 1e-8, name: str = None):
+        """Perfectly Matched Layer
+
+        Args:
+            a: stability parameter
+            name: name of the PML
+        """
+        super().__init__(name=name)
+
+        # TODO: to make this a PML parameter, the *normal* curl equations need to be updated
+        self.k = 1.0
+        self.thickness = 0
+
+        self.a = a
+
+    def _set_locations(self):
+        """helper function
+
+        sets:
+            self.loc: the location of the PML
+            self.locx: the location of the PML (only x coordinates)
+            self.locy: the location of the PML (only y coordinates)
+            self.locz: the location of the PML (only z coordinates)
+        """
+        raise NotImplementedError
+
+    def _set_shape(self):
+        """helper function
+
+        sets:
+            self.shape: the shape of the PML
+        """
+        raise NotImplementedError
+
+    def _set_sigmaE(self):
+        """helper function
+
+        sets:
+            self.sigmaE: the electric conductivity (responsible for the absorption) of
+                the PML
+        """
+        raise NotImplementedError
+
+    def _set_sigmaH(self):
+        """helper function
+
+        sets:
+            self.sigmaH: the magnetic conductivity (responsible for the absorption) of
+                the PML
+        """
+        raise NotImplementedError
+
+    def _sigma(self, vect: Tensorlike):
+        """create a cubicly increasing profile for the conductivity"""
+        return 40 * vect**3 / (self.thickness + 1) ** 4
+
+    def _register_grid(
+        self, grid: Grid, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ):
+
+        super()._register_grid(grid=grid, x=x, y=y, z=z)
+
+        if (
+            (self.x.start is None or self.x.start == 0)
+            and (self.x.stop is not None)
+            and (self.x.stop > 0)
+        ):
+            self.__class__ = _PMLXlow
+            if hasattr(grid, "_xlow_boundary"):
+                raise AttributeError("grid already has an xlow boundary!")
+            setattr(grid, "_xlow_boundary", self)
+            self._calculate_parameters(thickness=self.x.stop)
+        elif (
+            (self.x.start is not None) and (self.x.stop is None) and (self.x.start < 0)
+        ):
+            self.__class__ = _PMLXhigh
+            if hasattr(grid, "_xhigh_boundary"):
+                raise AttributeError("grid already has an xhigh boundary!")
+            setattr(grid, "_xhigh_boundary", self)
+            self._calculate_parameters(thickness=-self.x.start)
+        elif (
+            (self.y.start is None or self.y.start == 0)
+            and (self.y.stop is not None)
+            and (self.y.stop > 0)
+        ):
+            self.__class__ = _PMLYlow
+            if hasattr(grid, "_ylow_boundary"):
+                raise AttributeError("grid already has an ylow boundary!")
+            setattr(grid, "_ylow_boundary", self)
+            self._calculate_parameters(thickness=self.y.stop)
+        elif (
+            (self.y.start is not None) and (self.y.stop is None) and (self.y.start < 0)
+        ):
+            self.__class__ = _PMLYhigh
+            if hasattr(grid, "_yhigh_boundary"):
+                raise AttributeError("grid already has an yhigh boundary!")
+            setattr(grid, "_yhigh_boundary", self)
+            self._calculate_parameters(thickness=-self.y.start)
+        elif (
+            (self.z.start is None or self.z.start == 0)
+            and (self.z.stop is not None)
+            and (self.z.stop > 0)
+        ):
+            self.__class__ = _PMLZlow
+            if hasattr(grid, "_zlow_boundary"):
+                raise AttributeError("grid already has an zlow boundary!")
+            setattr(grid, "_zlow_boundary", self)
+            self._calculate_parameters(thickness=self.z.stop)
+        elif (
+            (self.z.start is not None) and (self.z.stop is None) and (self.z.start < 0)
+        ):
+            self.__class__ = _PMLZhigh
+            if hasattr(grid, "_zhigh_boundary"):
+                raise AttributeError("grid already has an zhigh boundary!")
+            setattr(grid, "_zhigh_boundary", self)
+            self._calculate_parameters(thickness=-self.z.start)
+        else:
+            raise IndexError(
+                "not a valid slice for a PML. Make sure the slice is at the border of the PML"
+            )
+
+    def _handle_slice(self, s: ListOrSlice) -> slice:
+        if isinstance(s, list):
+            raise ValueError("One can only use slices to index the grid for a PML")
+        if isinstance(s, slice):
+            return s
+        raise ValueError("Invalid grid indexing used for boundary")
+
+    def _calculate_parameters(self, thickness: int = 10):
+        """Calculate the parameters for the PML
+
+        Args:
+            thickness=10: The thickness of the PML. The thickness can be specified as
+                integer [gridpoints] or as float [meters].
+        """
+
+        self.thickness = thickness
+
+        # set orientation dependent parameters: (different for x, y, z-PML)
+        # NOTE: these methods are implemented by the subclasses of PML.
+        self._set_locations()
+        self._set_shape()
+        self._set_sigmaE()
+        self._set_sigmaH()
+
+        # set the other parameters
+        Nx, Ny, Nz = self.shape  # is defined by _set_shape()
+        self.phi_E = bd.zeros((Nx, Ny, Nz, 3))
+        self.phi_H = bd.zeros((Nx, Ny, Nz, 3))
+        self.psi_Ex = bd.zeros((Nx, Ny, Nz, 3))
+        self.psi_Ey = bd.zeros((Nx, Ny, Nz, 3))
+        self.psi_Ez = bd.zeros((Nx, Ny, Nz, 3))
+        self.psi_Hx = bd.zeros((Nx, Ny, Nz, 3))
+        self.psi_Hy = bd.zeros((Nx, Ny, Nz, 3))
+        self.psi_Hz = bd.zeros((Nx, Ny, Nz, 3))
+
+        self.bE = bd.exp(-(self.sigmaE / self.k + self.a) * self.grid.courant_number)
+        self.cE = (
+            (self.bE - 1.0)
+            * self.sigmaE  # is defined by _set_sigmaE()
+            / (self.sigmaE * self.k + self.a * self.k**2)
+        )
+
+        self.bH = bd.exp(-(self.sigmaH / self.k + self.a) * self.grid.courant_number)
+        self.cH = (
+            (self.bH - 1.0)
+            * self.sigmaH  # is defined by _set_sigmaH()
+            / (self.sigmaH * self.k + self.a * self.k**2)
+        )
+
+    def update_E(self):
+        """Update electric field of the grid
+
+        Note:
+            this method is called *after* the electric field is updated
+        """
+        self.grid.E[self.loc] += (
+            self.grid.courant_number
+            * self.grid.inverse_permittivity[self.loc]
+            * self.phi_E
+        )
+
+    def update_H(self):
+        """Update magnetic field of the grid
+
+        Note:
+            this method is called *after* the magnetic field is updated
+        """
+        self.grid.H[self.loc] -= (
+            self.grid.courant_number
+            * self.grid.inverse_permeability[self.loc]
+            * self.phi_H
+        )
+
+    def update_phi_E(self):
+        """Update convolution [phi_E]
+
+        Note:
+            this method is called *before* the electric field is updated
+        """
+        self.psi_Ex *= self.bE
+        self.psi_Ey *= self.bE
+        self.psi_Ez *= self.bE
+
+        c = self.cE
+        Hx = self.grid.H[self.locx]
+        Hy = self.grid.H[self.locy]
+        Hz = self.grid.H[self.locz]
+
+        self.psi_Ex[:, 1:, :, 1] += (Hz[:, 1:, :] - Hz[:, :-1, :]) * c[:, 1:, :, 1]
+        self.psi_Ex[:, :, 1:, 2] += (Hy[:, :, 1:] - Hy[:, :, :-1]) * c[:, :, 1:, 2]
+
+        self.psi_Ey[:, :, 1:, 2] += (Hx[:, :, 1:] - Hx[:, :, :-1]) * c[:, :, 1:, 2]
+        self.psi_Ey[1:, :, :, 0] += (Hz[1:, :, :] - Hz[:-1, :, :]) * c[1:, :, :, 0]
+
+        self.psi_Ez[1:, :, :, 0] += (Hy[1:, :, :] - Hy[:-1, :, :]) * c[1:, :, :, 0]
+        self.psi_Ez[:, 1:, :, 1] += (Hx[:, 1:, :] - Hx[:, :-1, :]) * c[:, 1:, :, 1]
+
+        self.phi_E[..., 0] = self.psi_Ex[..., 1] - self.psi_Ex[..., 2]
+        self.phi_E[..., 1] = self.psi_Ey[..., 2] - self.psi_Ey[..., 0]
+        self.phi_E[..., 2] = self.psi_Ez[..., 0] - self.psi_Ez[..., 1]
+
+    def update_phi_H(self):
+        """Update convolution [phi_H]
+
+        Note:
+            this method is called *before* the magnetic field is updated
+        """
+        self.psi_Hx *= self.bH
+        self.psi_Hy *= self.bH
+        self.psi_Hz *= self.bH
+
+        c = self.cH
+        Ex = self.grid.E[self.locx]
+        Ey = self.grid.E[self.locy]
+        Ez = self.grid.E[self.locz]
+
+        self.psi_Hx[:, :-1, :, 1] += (Ez[:, 1:, :] - Ez[:, :-1, :]) * c[:, :-1, :, 1]
+        self.psi_Hx[:, :, :-1, 2] += (Ey[:, :, 1:] - Ey[:, :, :-1]) * c[:, :, :-1, 2]
+
+        self.psi_Hy[:, :, :-1, 2] += (Ex[:, :, 1:] - Ex[:, :, :-1]) * c[:, :, :-1, 2]
+        self.psi_Hy[:-1, :, :, 0] += (Ez[1:, :, :] - Ez[:-1, :, :]) * c[:-1, :, :, 0]
+
+        self.psi_Hz[:-1, :, :, 0] += (Ey[1:, :, :] - Ey[:-1, :, :]) * c[:-1, :, :, 0]
+        self.psi_Hz[:, :-1, :, 1] += (Ex[:, 1:, :] - Ex[:, :-1, :]) * c[:, :-1, :, 1]
+
+        self.phi_H[..., 0] = self.psi_Hx[..., 1] - self.psi_Hx[..., 2]
+        self.phi_H[..., 1] = self.psi_Hy[..., 2] - self.psi_Hy[..., 0]
+        self.phi_H[..., 2] = self.psi_Hz[..., 0] - self.psi_Hz[..., 1]
+
+
+class _PMLXlow(PML):
+    """A perfectly matched layer to place where X is low."""
+
+    def _set_locations(self):
+        self.loc = (slice(None, self.thickness), slice(None), slice(None), slice(None))
+        self.locx = (slice(None, self.thickness), slice(None), slice(None), 0)
+        self.locy = (slice(None, self.thickness), slice(None), slice(None), 1)
+        self.locz = (slice(None, self.thickness), slice(None), slice(None), 2)
+
+    def _set_shape(self):
+        self.shape = (self.thickness, self.grid.Ny, self.grid.Nz)
+
+    def _set_sigmaE(self):
+        sigma = self._sigma(bd.arange(self.thickness - 0.5, -0.5, -1.0))
+        self.sigmaE = bd.zeros((self.thickness, self.grid.Ny, self.grid.Nz, 3))
+        self.sigmaE[:, :, :, 0] = sigma[:, None, None]
+
+    def _set_sigmaH(self):
+        sigma = self._sigma(bd.arange(self.thickness - 1.0, 0, -1.0))
+        self.sigmaH = bd.zeros((self.thickness, self.grid.Ny, self.grid.Nz, 3))
+        self.sigmaH[:-1, :, :, 0] = sigma[:, None, None]
+
+
+class _PMLXhigh(PML):
+    """A perfectly matched layer to place where X is high."""
+
+    def _set_locations(self):
+        self.loc = (slice(-self.thickness, None), slice(None), slice(None), slice(None))
+        self.locx = (slice(-self.thickness, None), slice(None), slice(None), 0)
+        self.locy = (slice(-self.thickness, None), slice(None), slice(None), 1)
+        self.locz = (slice(-self.thickness, None), slice(None), slice(None), 2)
+
+    def _set_shape(self):
+        self.shape = (self.thickness, self.grid.Ny, self.grid.Nz)
+
+    def _set_sigmaE(self):
+        sigma = self._sigma(bd.arange(0.5, self.thickness + 0.5, 1.0))
+        self.sigmaE = bd.zeros((self.thickness, self.grid.Ny, self.grid.Nz, 3))
+        self.sigmaE[:, :, :, 0] = sigma[:, None, None]
+
+    def _set_sigmaH(self):
+        sigma = self._sigma(bd.arange(1.0, self.thickness, 1.0))
+        self.sigmaH = bd.zeros((self.thickness, self.grid.Ny, self.grid.Nz, 3))
+        self.sigmaH[:-1, :, :, 0] = sigma[:, None, None]
+
+
+class _PMLYlow(PML):
+    """A perfectly matched layer to place where Y is low."""
+
+    def _set_locations(self):
+        self.loc = (slice(None), slice(None, self.thickness), slice(None))
+        self.locx = (slice(None), slice(None, self.thickness), slice(None), 0)
+        self.locy = (slice(None), slice(None, self.thickness), slice(None), 1)
+        self.locz = (slice(None), slice(None, self.thickness), slice(None), 2)
+
+    def _set_shape(self):
+        self.shape = (self.grid.Nx, self.thickness, self.grid.Nz)
+
+    def _set_sigmaE(self):
+        sigma = self._sigma(bd.arange(self.thickness - 0.5, -0.5, -1.0))
+        self.sigmaE = bd.zeros((self.grid.Nx, self.thickness, self.grid.Nz, 3))
+        self.sigmaE[:, :, :, 1] = sigma[None, :, None]
+
+    def _set_sigmaH(self):
+        sigma = self._sigma(bd.arange(self.thickness - 1.0, 0, -1.0))
+        self.sigmaH = bd.zeros((self.grid.Nx, self.thickness, self.grid.Nz, 3))
+        self.sigmaH[:, :-1, :, 1] = sigma[None, :, None]
+
+
+class _PMLYhigh(PML):
+    """A perfectly matched layer to place where Y is high."""
+
+    def _set_locations(self):
+        self.loc = (slice(None), slice(-self.thickness, None), slice(None), slice(None))
+        self.locx = (slice(None), slice(-self.thickness, None), slice(None), 0)
+        self.locy = (slice(None), slice(-self.thickness, None), slice(None), 1)
+        self.locz = (slice(None), slice(-self.thickness, None), slice(None), 2)
+
+    def _set_shape(self):
+        self.shape = (self.grid.Nx, self.thickness, self.grid.Nz)
+
+    def _set_sigmaE(self):
+        sigma = self._sigma(bd.arange(0.5, self.thickness + 0.5, 1.0))
+        self.sigmaE = bd.zeros((self.grid.Nx, self.thickness, self.grid.Nz, 3))
+        self.sigmaE[:, :, :, 1] = sigma[None, :, None]
+
+    def _set_sigmaH(self):
+        sigma = self._sigma(bd.arange(1.0, self.thickness, 1.0))
+        self.sigmaH = bd.zeros((self.grid.Nx, self.thickness, self.grid.Nz, 3))
+        self.sigmaH[:, :-1, :, 1] = sigma[None, :, None]
+
+
+class _PMLZlow(PML):
+    """A perfectly matched layer to place where Z is low."""
+
+    def _set_locations(self):
+        self.loc = (slice(None), slice(None), slice(None, self.thickness), slice(None))
+        self.locx = (slice(None), slice(None), slice(None, self.thickness), 0)
+        self.locy = (slice(None), slice(None), slice(None, self.thickness), 1)
+        self.locz = (slice(None), slice(None), slice(None, self.thickness), 2)
+
+    def _set_shape(self):
+        self.shape = (self.grid.Nx, self.grid.Ny, self.thickness)
+
+    def _set_sigmaE(self):
+        sigma = self._sigma(bd.arange(self.thickness - 0.5, -0.5, -1.0))
+        self.sigmaE = bd.zeros((self.grid.Nx, self.grid.Ny, self.thickness, 3))
+        self.sigmaE[:, :, :, 2] = sigma[None, None, :]
+
+    def _set_sigmaH(self):
+        sigma = self._sigma(bd.arange(self.thickness - 1.0, 0, -1.0))
+        self.sigmaH = bd.zeros((self.grid.Nx, self.grid.Ny, self.thickness, 3))
+        self.sigmaH[:, :, :-1, 2] = sigma[None, None, :]
+
+
+class _PMLZhigh(PML):
+    """A perfectly matched layer to place where Z is high."""
+
+    def _set_locations(self):
+        self.loc = (slice(None), slice(None), slice(-self.thickness, None), slice(None))
+        self.locx = (slice(None), slice(None), slice(-self.thickness, None), 0)
+        self.locy = (slice(None), slice(None), slice(-self.thickness, None), 1)
+        self.locz = (slice(None), slice(None), slice(-self.thickness, None), 2)
+
+    def _set_shape(self):
+        self.shape = (self.grid.Nx, self.grid.Ny, self.thickness)
+
+    def _set_sigmaE(self):
+        sigma = self._sigma(bd.arange(0.5, self.thickness + 0.5, 1.0))
+        self.sigmaE = bd.zeros((self.grid.Nx, self.grid.Ny, self.thickness, 3))
+        self.sigmaE[:, :, :, 2] = sigma[None, None, :]
+
+    def _set_sigmaH(self):
+        sigma = self._sigma(bd.arange(1.0, self.thickness, 1.0))
+        self.sigmaH = bd.zeros((self.grid.Nx, self.grid.Ny, self.thickness, 3))
+        self.sigmaH[:, :, :-1, 2] = sigma[None, None, :]
+
+
+def DomainBorderPML(grid, border_cells=5):
+    """
+    Some problem setups require a layer of PML all the way around the problem.
+    This is a convenience function to add such a layer to an existing grid.
+    Caution: Alters grid in-place.
+    """
+    # Doesn't return anything, unlike other .boundaries functions - is that breaking the API?
+    # There might be a more straightforward numpy slicing solution...
+    # maybe with
+    # raw = np.pad(raw, [(pcb.pml_cells, pcb.pml_cells), (pcb.pml_cells, pcb.pml_cells),
+    #    (pcb.pml_cells, pcb.pml_cells)], mode='constant') and then indexing the grid by that?
+
+    if (
+        grid.Nx < border_cells * 2
+        or grid.Ny < border_cells * 2
+        or grid.Nz < border_cells * 2
+    ):
+        raise IndexError("PML border_cells larger than domain!")
+
+    # overly-complicated slicing doesn't overlap,
+    # haven't checked if that's important
+
+    # top and bottom
+    grid[:, :, 0:border_cells] = PML()
+    grid[:, :, -border_cells:] = PML()
+
+    # left and right
+    grid[0:border_cells, :, border_cells:-border_cells] = PML()
+    grid[-border_cells:, :, border_cells:-border_cells] = PML()
+
+    # front and back
+    grid[border_cells:-border_cells, 0:border_cells, border_cells:-border_cells] = PML()
+    grid[border_cells:-border_cells, -border_cells:, border_cells:-border_cells] = PML()
diff --git a/nidn/fdtd/compute_spectrum.py b/nidn/fdtd/compute_spectrum.py
deleted file mode 100644
index 4a92b1a..0000000
--- a/nidn/fdtd/compute_spectrum.py
+++ /dev/null
@@ -1,104 +0,0 @@
-from weakref import ref
-from dotmap import DotMap
-import sys
-
-import torch
-from nidn.fdtd.calculate_transmission_reflection_coefficients import (
-    calculate_transmission_reflection_coefficients,
-)
-
-from nidn.trcwa.constants import TRCWA_EPS_0
-
-sys.path.append("../")
-import nidn
-from init_fdtd import init_fdtd
-
-
-def compute_spectrum(cfg: DotMap):
-    """Generates a spectrum of transmission and reflection coefficients for the specified wavelengths in the cfg, by using FDTD simulations.
-
-    Args:
-        cfg (DotMap): Configurations needed to perform the simulations
-
-    Returns:
-        tuple[array, array]: Transmission spectrum and reflection spectrum
-    """
-    t_spectrum, r_spectrum = []
-    physical_wavelengths, norm_freq = nidn.get_frequency_points(cfg)
-
-    for w in physical_wavelengths:
-        transmission, reflection = []
-        grid, t_detector, r_detector = init_fdtd(cfg, False, w, permittivity=5.1984)
-        grid.run(cfg.FDTD_niter, progress_bar=False)
-        transmission[0], reflection[0] = _get_detector_values(
-            t_detector, r_detector, cfg.FDTD_grid[2] / 2
-        )
-
-        grid, t_detector, r_detector = init_fdtd(cfg, True, w, permittivity=5.1984)
-        grid.run(cfg.FDTD_niter, progress_bar=True)
-        transmission[1], reflection[1] = _get_detector_values(
-            t_detector, r_detector, cfg.FDTD_grid[2] / 2
-        )
-
-        (
-            transmission_coefficient,
-            reflection_coefficient,
-        ) = calculate_transmission_reflection_coefficients(
-            transmission, reflection, "MEAN SQUARE"
-        )
-        t_spectrum.append(transmission_coefficient)
-        r_spectrum.append(reflection_coefficient)
-
-    # For each wavelength:
-    # Run simulation
-    # Get detector values
-    # Postprocess signal,  i.e. phase shift and more if applicable
-    # Calculate transmission, reflection (and absorption coefficients)
-    # Return transmission spectrum, reflection spectrum (and absorption spectrum)
-    return t_spectrum, r_spectrum
-
-
-def _get_detector_values(
-    transmission_detector, reflection_detector, detector_position_y
-):
-    """Extract the signals detected by the transmission detector and the reflection detector
-
-    Args:
-        transmission_detector (fdtd.LineDetector): The transmission detector attached to the grid
-        reflection_detector (fdtd.LineDetector): The reflection detector attached to the grid
-        detector_position_y (int): The position along the linedetector which should be used
-
-    Returns:
-        tuple[array, array]: The electric field detected by the transmission detector, and the electric field detected by the reflection detector
-    """
-    e_transmission = _get_abs_value_from_3D_signal(
-        transmission_detector.detector_values["E"][int(detector_position_y)]
-    )
-    e_reflection = _get_abs_value_from_3D_signal(
-        reflection_detector.detector_values["E"][int(detector_position_y)]
-    )
-    h_transmission = _get_abs_value_from_3D_signal(
-        transmission_detector.detector_values["H"][int(detector_position_y)]
-    )
-    h_reflection = _get_abs_value_from_3D_signal(
-        reflection_detector.detector_values["H"][int(detector_position_y)]
-    )
-
-    return e_transmission, e_reflection
-
-
-def _get_abs_value_from_3D_signal(signal):
-    """Get the absolute value of a three-dimentional signal. For each time step, a =sqrt(x**2 + y**2 + z**2)
-
-    Args:
-        signal (array): Three dimentional time signal
-
-    Returns:
-        Array: One dimentional time-signal
-    """
-    abs_value = []
-    for i in range(len(signal)):
-        abs_value.append(
-            torch.sqrt(signal[i][0] ** 2 + signal[i][1] ** 2 + signal[i][2] ** 2)
-        )
-    return abs_value
diff --git a/nidn/fdtd/constants.py b/nidn/fdtd/constants.py
index 40fb63d..f4212f8 100644
--- a/nidn/fdtd/constants.py
+++ b/nidn/fdtd/constants.py
@@ -1,1 +1,10 @@
-FDTD_UNIT_MAGNITUDE = 10 ** (-6)
\ No newline at end of file
+""" often used constants go here """
+
+FDTD_X: int = 0
+""" x-index (useful for indexing) """
+
+FDTD_Y: int = 1
+""" y-index (useful for indexing) """
+
+FDTD_Z: int = 2
+""" z-index (useful for indexing) """
diff --git a/nidn/fdtd/conversions.py b/nidn/fdtd/conversions.py
new file mode 100644
index 0000000..1187bb2
--- /dev/null
+++ b/nidn/fdtd/conversions.py
@@ -0,0 +1,45 @@
+from math import sqrt
+
+from nidn.utils.global_constants import EPS_0, MU_0
+
+"""
+Optional reduced unit conversion functions for user use.
+Mainly to make it explicit where conversions happen.
+
+Unit system described by the thesis
+"Novel architectures for brain-inspired photonic computers",
+https://www.photonics.intec.ugent.be/download/phd_259.pdf
+
+Chapters 4.1.2 and 4.1.6.
+
+> "In SI units, the relative magnitude difference between the fields is related
+by the electromagnetic impedance of free space, which for the current choice
+of simulation units equals 1 per definition".
+
+FIXME: DC: find and add md notes on scaling
+
+"""
+
+# Might perhaps be worth putting a note in the readme about default units / suggested unit systems?
+# (done, see next PR)
+# Also, if /fdtd/ gets the ability to dump to VTK, one would hate to
+# have to scale everything for physical results in paraview. Will put a scaling option there.
+# Is it reasonable to have a global flag for scaling? probably not
+#
+# don't know how severe noise is with fp32, whether it's worth the extra hassle for most people
+
+
+def simE_to_worldE(input):
+    return input / sqrt(EPS_0)
+
+
+def worldE_to_simE(input):
+    return sqrt(EPS_0) * input
+
+
+def simH_to_worldH(input):
+    return input / sqrt(MU_0)
+
+
+def worldH_to_simH(input):
+    return sqrt(MU_0) * input
diff --git a/nidn/fdtd/detectors.py b/nidn/fdtd/detectors.py
new file mode 100644
index 0000000..37304b3
--- /dev/null
+++ b/nidn/fdtd/detectors.py
@@ -0,0 +1,496 @@
+""" Detectors for the FDTD Grid.
+
+Available Detectors:
+
+ - LineDetector
+
+"""
+
+## Imports
+
+# typing
+from .typing_ import ListOrSlice, Tuple, List
+
+# relative
+from .grid import Grid
+from .backend import backend as bd
+from .constants import X, Y, Z
+
+## Detector
+class LineDetector:
+    """A detector along a line in the FDTD grid"""
+
+    def __init__(self, name=None):
+        """Create a line detector
+
+        Args:
+            name: name of the Detector
+
+        """
+        self.grid = None
+        self.E = []
+        self.H = []
+        self.name = name
+
+    def _register_grid(
+        self, grid: Grid, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ):
+        """Register a grid to the detector
+
+        Args:
+            grid: the grid to place the detector into
+            x: the x-location of the detector in the grid
+            y: the y-location of the detector in the grid
+            z: the z-location of the detector in the grid
+
+        Note:
+            As its name suggests, this detector is a LINE detector.
+            Hence the detector spans the diagonal of the cube
+            defined by the slices in the grid.
+        """
+        self.grid = grid
+        self.grid.detectors.append(self)
+        if self.name is not None:
+            if not hasattr(grid, self.name):
+                setattr(grid, self.name, self)
+            else:
+                raise ValueError(
+                    f"The grid already has an attribute with name {self.name}"
+                )
+
+        self.x, self.y, self.z = self._handle_slices(x, y, z)
+
+    def _handle_slices(
+        self, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ) -> Tuple[List, List, List]:
+        """Convert slices in the grid to lists
+
+        This is necessary to make the source span the diagonal of the volume
+        defined by the slices.
+
+        Args:
+            x: The x-location of the volume in the grid
+            y: The y-location of the volume in the grid
+            z: The z-location of the volume in the grid
+
+        Returns:
+            x, y, z: the x, y and z coordinates of the source as lists
+
+        """
+
+        # if list-indices were chosen:
+        if isinstance(x, list) and isinstance(y, list) and isinstance(z, list):
+            if len(x) != len(y) or len(y) != len(z) or len(z) != len(x):
+                raise IndexError(
+                    "sources require grid to be indexed with slices or equal length list-indices"
+                )
+            return x, y, z
+
+        # if a combination of list-indices and slices were chosen,
+        # convert the list-indices to slices.
+        # TODO: maybe issue a warning here?
+        if isinstance(x, list):
+            x = slice(x[0], x[-1], None)
+        if isinstance(y, list):
+            y = slice(y[0], y[-1], None)
+        if isinstance(z, list):
+            z = slice(z[0], z[-1], None)
+
+        # if we get here, we can assume slices:
+        x0 = x.start if x.start is not None else 0
+        y0 = y.start if y.start is not None else 0
+        z0 = z.start if z.start is not None else 0
+        x1 = x.stop if x.stop is not None else self.grid.Nx
+        y1 = y.stop if y.stop is not None else self.grid.Ny
+        z1 = z.stop if z.stop is not None else self.grid.Nz
+
+        # we can now convert these coordinates into index lists
+        m = max(abs(x1 - x0), abs(y1 - y0), abs(z1 - z0))
+        x = [v.item() for v in bd.array(bd.linspace(x0, x1, m, endpoint=False), bd.int)]
+        y = [v.item() for v in bd.array(bd.linspace(y0, y1, m, endpoint=False), bd.int)]
+        z = [v.item() for v in bd.array(bd.linspace(z0, z1, m, endpoint=False), bd.int)]
+        return x, y, z
+
+    def detect_E(self):
+        """detect the electric field at a certain location in the grid"""
+        # TODO: there is a performance bottleneck here (indexing with lists)
+        E = self.grid.E[self.x, self.y, self.z]
+        self.E.append(E)
+
+    def detect_H(self):
+        """detect the magnetic field at a certain location in the grid"""
+        # TODO: there is a performance bottleneck here (indexing with lists)
+        H = self.grid.H[self.x, self.y, self.z]
+        self.H.append(H)
+
+    def __repr__(self):
+        return f"{self.__class__.__name__}(name={repr(self.name)})"
+
+    def __str__(self):
+        s = "    " + repr(self) + "\n"
+        x = f"[{self.x[0]}, ... , {self.x[-1]}]"
+        y = f"[{self.y[0]}, ... , {self.y[-1]}]"
+        z = f"[{self.z[0]}, ... , {self.z[-1]}]"
+        s += f"        @ x={x}, y={y}, z={z}\n"
+        return s
+
+    def detector_values(self):
+        """outputs what detector detects"""
+        return {"E": self.E, "H": self.H}
+
+
+# is the "detector" paradigm necessary? Can we just flag a segment of the base mesh to be
+# stored per timestep?
+
+## BlockDetector
+class BlockDetector:
+    """A detector along a block in the FDTD grid"""
+
+    """ Basic copy of LineDetector code, changed detect functions """
+
+    def __init__(self, name=None):
+        """Create a block detector
+
+        Args:
+            name: name of the Detector
+
+        """
+        self.grid = None
+        self.E = []
+        self.H = []
+        self.name = name
+
+    def _register_grid(
+        self, grid: Grid, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ):
+        """Register a grid to the detector
+
+        Args:
+            grid: the grid to place the detector into
+            x: the x-location of the detector in the grid
+            y: the y-location of the detector in the grid
+            z: the z-location of the detector in the grid
+
+        Note:
+            As its name suggests, this detector is a BLOCK detector.
+            Hence the detector spans the VOLUME of the cube
+            defined by the slices in the grid.
+        """
+        self.grid = grid
+        self.grid.detectors.append(self)
+        if self.name is not None:
+            if not hasattr(grid, self.name):
+                setattr(grid, self.name, self)
+            else:
+                raise ValueError(
+                    f"The grid already has an attribute with name {self.name}"
+                )
+
+        self.x, self.y, self.z = self._handle_slices(x, y, z)
+
+    def _handle_slices(
+        self, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ) -> Tuple[List, List, List]:
+        """Convert slices in the grid to lists
+
+        This is necessary to make the source span the volume
+        defined by the slices.
+
+        Args:
+            x: The x-location of the volume in the grid
+            y: The y-location of the volume in the grid
+            z: The z-location of the volume in the grid
+
+        Returns:
+            x, y, z: the x, y and z coordinates of the source as lists
+
+        """
+
+        # if list-indices were chosen:
+        if isinstance(x, list) and isinstance(y, list) and isinstance(z, list):
+            if len(x) != len(y) or len(y) != len(z) or len(z) != len(x):
+                raise IndexError(
+                    "sources require grid to be indexed with slices or equal length list-indices"
+                )
+            return x, y, z
+
+        # if a combination of list-indices and slices were chosen,
+        # convert the list-indices to slices.
+        # TODO: maybe issue a warning here?
+        if isinstance(x, list):
+            x = slice(x[0], x[-1], None)
+        if isinstance(y, list):
+            y = slice(y[0], y[-1], None)
+        if isinstance(z, list):
+            z = slice(z[0], z[-1], None)
+
+        # if we get here, we can assume slices:
+        x0 = x.start if x.start is not None else 0
+        y0 = y.start if y.start is not None else 0
+        z0 = z.start if z.start is not None else 0
+        x1 = x.stop if x.stop is not None else self.grid.Nx
+        y1 = y.stop if y.stop is not None else self.grid.Ny
+        z1 = z.stop if z.stop is not None else self.grid.Nz
+
+        # we can now convert these coordinates into index lists
+        x = [v.item() for v in bd.arange(x0, x1 + 1)]
+        y = [v.item() for v in bd.arange(y0, y1 + 1)]
+        z = [v.item() for v in bd.arange(z0, z1 + 1)]
+        return x, y, z
+
+    def detect_E(self):
+        """detect the electric field at a certain location in the grid"""
+        # TODO: there is a performance bottleneck here (indexing with lists)
+        E = []
+        for i, row in enumerate(self.x):
+            E.append([])
+            for j, col in enumerate(self.y):
+                E[i].append([])
+                for pillar in self.z:
+                    E[i][j].append(self.grid.E[row, col, [pillar]][0])
+        # E = self.grid.E[self.x, self.y, self.z]
+        self.E.append(E)
+
+    def detect_H(self):
+        """detect the magnetic field at a certain location in the grid"""
+        # TODO: there is a performance bottleneck here (indexing with lists)
+        H = []
+        for i, row in enumerate(self.x):
+            H.append([])
+            for j, col in enumerate(self.y):
+                H[i].append([])
+                for pillar in self.z:
+                    H[i][j].append(self.grid.H[row, col, [pillar]][0])
+        # H = self.grid.H[self.x, self.y, self.z]
+        self.H.append(H)
+
+    def __repr__(self):
+        return f"{self.__class__.__name__}(name={repr(self.name)})"
+
+    def __str__(self):
+        s = "    " + repr(self) + "\n"
+        x = f"[{self.x[0]}, ... , {self.x[-1]}]"
+        y = f"[{self.y[0]}, ... , {self.y[-1]}]"
+        z = f"[{self.z[0]}, ... , {self.z[-1]}]"
+        s += f"        @ x={x}, y={y}, z={z}\n"
+        return s
+
+    def detector_values(self):
+        """outputs what detector detects"""
+        return {"E": self.E, "H": self.H}
+
+
+## CurrentDetector
+class CurrentDetector:
+    """A current detector."""
+
+    """
+
+
+
+    """
+
+    # Alternative APIs:
+    #
+    # 1. Current detection could be a standard detector output,
+    # if every h-field probe pointed two ways.
+    # 2. No current detector class at all. SoftArbitraryPointSource
+    # makes two H-detectors. (can't test separated then).
+    # Don't know if this op over a volume is valid. Should be.
+    # TODO: Detector geometry as an argument?
+    # Lots of interesting I detector geometries that might be worth implementing,
+    # ("integrated current loop"), this could be a flag here.
+    #
+    # Existing sources are all z-polarized; E-detectors output all the polarizations.
+    # Unlike other Detectors, this does not yet output a polarized current!
+    #
+    # *Source* polarization is probably an important feature for 3D electrical work
+    # not sure how important it is for optical stuff
+
+    def __init__(self, name=None):
+        """Create a block detector
+
+        Args:
+            name: name of the Detector
+
+        """
+        self.grid = None
+        self.orientation = None
+        self.I = []
+        self.name = name
+
+    def _register_grid(
+        self, grid: Grid, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ):
+        """Register a grid to the detector
+
+        Args:
+            grid: the grid to place the detector into
+            x: the x-location of the detector in the grid
+            y: the y-location of the detector in the grid
+            z: the z-location of the detector in the grid
+            orientation: a unit vector (a length 1) describing the orientation?
+
+        Note:
+            As its name suggests, this detector is a BLOCK detector.
+            Hence the detector spans the VOLUME of the cube
+            defined by the slices in the grid.
+        """
+        self.grid = grid
+        self.grid.detectors.append(self)
+        if self.name is not None:
+            if not hasattr(grid, self.name):
+                setattr(grid, self.name, self)
+            else:
+                raise ValueError(
+                    f"The grid already has an attribute with name {self.name}"
+                )
+
+        self.x, self.y, self.z = self._handle_slices(x, y, z)
+
+    def _handle_slices(
+        self, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ) -> Tuple[List, List, List]:
+        """Convert slices in the grid to lists
+
+        This is necessary to make the source span the volume
+        defined by the slices.
+
+        Args:
+            x: The x-location of the volume in the grid
+            y: The y-location of the volume in the grid
+            z: The z-location of the volume in the grid
+
+        Returns:
+            x, y, z: the x, y and z coordinates of the source as lists
+
+        """
+
+        # if list-indices were chosen:
+        if isinstance(x, list) and isinstance(y, list) and isinstance(z, list):
+            if len(x) != len(y) or len(y) != len(z) or len(z) != len(x):
+                raise IndexError(
+                    "sources require grid to be indexed with slices or equal length list-indices"
+                )
+            return x, y, z
+
+        # if a combination of list-indices and slices were chosen,
+        # convert the list-indices to slices.
+        # TODO: maybe issue a warning here?
+        if isinstance(x, list):
+            x = slice(x[0], x[-1], None)
+        if isinstance(y, list):
+            y = slice(y[0], y[-1], None)
+        if isinstance(z, list):
+            z = slice(z[0], z[-1], None)
+
+        # if we get here, we can assume slices:
+        x0 = x.start if x.start is not None else 0
+        y0 = y.start if y.start is not None else 0
+        z0 = z.start if z.start is not None else 0
+        x1 = x.stop if x.stop is not None else self.grid.Nx
+        y1 = y.stop if y.stop is not None else self.grid.Ny
+        z1 = z.stop if z.stop is not None else self.grid.Nz
+
+        # we can now convert these coordinates into index lists
+        x = [v.item() for v in bd.arange(x0, x1 + 1)]
+        y = [v.item() for v in bd.arange(y0, y1 + 1)]
+        z = [v.item() for v in bd.arange(z0, z1 + 1)]
+        return x, y, z
+
+    def detect_E(self):
+        """detect the electric field at a certain location in the grid"""
+
+    def single_point_current(self, px, py, pz):
+        """
+
+        Only Z-polarized for now. Can probably do a cross product to get arbitrary polarizations
+
+        ^
+        |
+        |
+        X---->
+
+        TODO: FIXME: IMPORTANT:
+        material magnetic permeability? find test cases!
+
+
+
+        Implements the first correction from [Fang 1994] (two
+        cells are spatially averaged to account for Yee cell half-step inaccuracies),
+        but not the second one (minor loss of accuracy).
+
+        Jiayuan Fang, Danwei Xue.
+        Precautions in the calculation of impedance in FDTD computations.
+        Proceedings of IEEE Antennas and Propagation Society International Symposium
+        and URSI National Radio Science Meeting, vol. 3, 1994, p. 1814–7 vol.3.
+        https://doi.org/10.1109/APS.1994.408185.
+
+
+        Luebbers RJ, Langdon HS.
+        A simple feed model that reduces time steps needed for
+        FDTD antenna and microstrip calculations.
+        IEEE Trans Antennas Propagat 1996;44:1000–5.
+        https://doi.org/10.1109/8.504308.
+
+        """
+
+        # [Luebbers 1996 1992]
+        # /sqrt(mu_0)s removed!
+
+        # option for unit factor here? Units will get very complicated otherwise
+
+        current_vector_1 = (
+            (self.grid.H[px, py - 1, pz, X]) - (self.grid.H[px, py, pz, X])
+        ) * self.grid.grid_spacing
+        current_vector_2 = (
+            (self.grid.H[px, py, pz, Y]) - (self.grid.H[px - 1, py, pz, Y])
+        ) * self.grid.grid_spacing
+
+        current_1 = current_vector_1 + current_vector_2
+        # current_1 = float(current.cpu())
+
+        current_vector_1 = (
+            (self.grid.H[px, py - 1, pz - 1, X]) - (self.grid.H[px, py, pz - 1, X])
+        ) * self.grid.grid_spacing
+        current_vector_2 += (
+            (self.grid.H[px, py, pz - 1, Y]) - (self.grid.H[px - 1, py, pz - 1, Y])
+        ) * self.grid.grid_spacing
+        # current_2 = float(current_2.cpu())
+        current_2 = current_vector_1 + current_vector_2
+
+        I = (current_1 + current_2) / 2.0
+
+        return I
+
+    def detect_H(self):
+
+        # should detector outputs be bd.array() by default?
+        # for that matter, should they always be converted to numpy?
+
+        I = []
+        for i, row in enumerate(self.x):
+            I.append([])
+            for j, col in enumerate(self.y):
+                I[i].append([])
+                for k, pillar in enumerate(self.z):
+                    I[i][j].append([])
+                    I[i][j][k] = self.single_point_current(row, col, pillar)
+
+        self.I.append(I)
+
+    # can these functions be templated somehow?
+    def __repr__(self):
+        return f"{self.__class__.__name__}(name={repr(self.name)})"
+
+    def __str__(self):
+        s = "    " + repr(self) + "\n"
+        x = f"[{self.x[0]}, ... , {self.x[-1]}]"
+        y = f"[{self.y[0]}, ... , {self.y[-1]}]"
+        z = f"[{self.z[0]}, ... , {self.z[-1]}]"
+        s += f"        @ x={x}, y={y}, z={z}\n"
+        return s
+
+    def detector_values(self):
+        """outputs what detector detects"""
+        return {"I": self.I}
diff --git a/nidn/fdtd/fourier.py b/nidn/fdtd/fourier.py
new file mode 100644
index 0000000..cc89654
--- /dev/null
+++ b/nidn/fdtd/fourier.py
@@ -0,0 +1,341 @@
+# def pretty_freqs():
+#     ["KHz", "MHz", "GHz", "THz"]
+#     {:.2f}"\
+#                 .format(fft_bin_resolution)
+
+# In the electrical domain,
+
+# https://inst.eecs.berkeley.edu/~ee232/sp17/discussions/Discussion%207%20-%20Photonic%20circuit%20simulation.pptx
+
+# in the optical domain, the impedance would just be that of free space?
+
+from math import ceil
+from .backend import backend as bd
+from .detectors import LineDetector, BlockDetector, CurrentDetector
+from .sources import SoftArbitraryPointSource
+
+
+class FrequencyRoutines:
+    # originally called FrequencyDomain, renamed because 'fd' is already a namespace
+
+    # inputs:
+    # One of, or a list of:
+    # - a single plain array or numpy array of values (like the waveform_array input to SoftArb)
+    # only works with FFT(), not impedance.
+    # The length does not need to correspond to the simulation length (e.g. it can be shorter);
+    # The timestep is assumed to be the same, however.
+    #
+    # - a single plain detector, of any type,
+    #
+    #
+    # - a single SoftArbitraryPointSource object,
+    # works with impedance or 1-port s-param,
+    # - an array of SoftArbitraryPointSource
+    # for multi-port S-param,
+    # - the tuple (detector, current_detector) or [(detector, current_detector),...]
+    # (the impedance is then assumed to be that of free-space).
+    # FIXME:
+    # free-space impedance should also eventually
+    # depend on the permittivity and permeability of the detector cell
+    #
+    # converts it into the frequency domain.
+    # frequency in Hz, not angular frequency
+
+    def __init__(self, grid, objs):
+        self.grid = grid
+        self.objs = objs
+
+    def compute_padding(
+        self,
+        input_data,
+        dt,
+        freq_window_tuple=None,
+        fft_num_bins_in_window=None,
+        fft_bin_freq_resolution=None,
+    ):
+        """
+        input_data must be a 1d array with the time history of one detector. the length of input_data
+        is expected to be the same as time_steps_passed.
+
+        Does not apply the padding to input_data,
+        since multiple vectors will probably need the same padding and it
+        seems to make more sense to do that in the caller.
+
+        - fft_num_bins
+        - FFT bin resolution (optional) Hz.
+        """
+
+        # This seems like magic - how could this be?
+
+        # the key is that indeed no extra information is being added;
+        # sinc interplolation
+
+        # https://dsp.stackexchange.com/questions/31783/mathematical-justification-for-zero-padding
+        # https://dsp.stackexchange.com/questions/741/why-should-i-zero-pad-a-signal-before-taking-the-fourier-transform
+        # https://dsp.stackexchange.com/questions/24410/zero-padding-of-fft/24426#24426
+
+        # Paraphrasing from the great explanation from
+        # https://www.bitweenie.com/listings/fft-zero-padding/
+        # there are two different frequency resolutions at play.
+        # The first one, a physical resolution,
+
+        # there are other ways to get a higher bin resolution without explicitly padding, too
+
+        input_length = input_data.shape[0]
+
+        if freq_window_tuple == None:
+            begin_freq = 0
+            # from numpy fftfreq docs
+            end_freq = (input_length / 2.0) / (dt * input_length)  # off by one?
+        else:
+            begin_freq, end_freq = freq_window_tuple
+
+        end_time = input_length * dt
+
+        if fft_num_bins_in_window == None and not fft_bin_freq_resolution == None:
+            fft_num_bins_in_window = (begin_freq - end_freq) / fft_bin_freq_resolution
+
+        elif not (fft_num_bins_in_window or fft_bin_freq_resolution):
+            # the window is the default, whole array (even if it's trimmed later)
+            fft_num_bins_in_window = input_data.shape[0]
+
+        waveform_frequency_resolution = 1.0 / end_time
+        fft_bin_resolution = (1.0 / dt) / (fft_num_bins_in_window)
+        print(
+            "Waveform data has an intrinsic resolution of: {:.2E} Hz".format(
+                waveform_frequency_resolution
+            )
+        )
+        print("FFT bin: {:.2E} Hz".format(fft_bin_resolution))
+
+        required_padding = (
+            ceil(fft_num_bins_in_window / ((end_freq - begin_freq) * dt)) - input_length
+        )
+
+        return required_padding, end_time
+
+        # assumes a uniform timestep. It might be useful to add a .times vector to the grid
+        # if the timestep is made variable at some point.
+        # on the other hand, doing a non-uniform FFT is probably non-trivial at this point anyway
+        # times = bd.linspace(0,end_time + (required_padding*dt),
+        #                                         (input_length+required_padding))
+
+    def compute_frequencies(self, length_with_padding, dt, freq_window_tuple=None):
+        """
+        Outputs the
+        The indexes are for the real-frequency part of the span.
+        """
+
+        spectrum_freqs = bd.fftfreq(length_with_padding, d=dt)
+
+        if freq_window_tuple == None:
+            begin_freq_idx = 0
+            # end_freq_idx = ((length_with_padding/2)-1)
+            end_freq_idx = -1
+        else:
+            # closest frequencies
+            begin_freq_idx = bd.abs(spectrum_freqs - begin_freq).argmin()
+            end_freq_idx = bd.abs(spectrum_freqs - end_freq).argmin()
+
+        return spectrum_freqs, begin_freq_idx, end_freq_idx
+
+    # UNTESTED
+    def S_parameters(waveform, node):
+        raise NotImplementedError
+        # outputs the S params for each frequency
+
+        # [1]Kurokawa K.
+        # Power Waves and the Scattering Matrix.
+        # IEEE Transactions on Microwave Theory and Techniques 1965
+        # ;13:194–202. https://doi.org/10.1109/TMTT.1965.1125964.
+
+        # Need to construct the matrix from Kurokawa "power wave" coefficients:
+        # a_1 =  #incident
+        # b_1 =  #reflected
+        # Wikipedia has a great section:
+        # https://en.wikipedia.org/wiki/Scattering_parameters
+
+        # inverse matrix?
+        #
+        # if(isinstance(self.objs, list)):
+        #
+        # elif(isinstance(self.objs,SoftArbitraryPointSource)):
+        # elif(isinstance(self.objs,tuple) and isinstance(self.objs[0],(BlockDetector,LineDetector))
+        #                                 and isinstance(self.objs[1],CurrentDetector)):
+        # else:
+        #     raise ValueError("Sorry, FFT can't yet interpret the argument given.")
+
+    def export_touchstone_s2p():
+        raise NotImplementedError
+
+    def FFT(
+        self,
+        freq_window_tuple=None,
+        fft_num_bins_in_window=None,
+        fft_bin_freq_resolution=None,
+    ):
+        """
+        FIXME: If is type BlockDetector or other similar output,
+        for now the fft of only one index is returned.
+        """
+        # scaling factor here?
+
+        if self.grid.time_steps_passed == 0:
+            return [], []
+        # I now see how Multiple Dispatch might be effective at speeding things up
+        if bd.is_array(self.objs):
+            input_data = self.objs
+        elif isinstance(self.objs, (LineDetector, BlockDetector)):
+            # FIXME:
+            input_data = self.objs.E[:][0][0][0]
+        elif isinstance(self.objs, SoftArbitraryPointSource):
+            # FIXME:
+            input_data = self.objs.source_voltage[:][0][0][0]
+        elif isinstance(self.objs, CurrentDetector):
+            # FIXME:
+            input_data = self.objs.I[:][0][0][0]
+        else:
+            raise ValueError("Sorry, FFT can't yet interpret the argument given.")
+
+        input_data = bd.array(input_data)
+        required_padding, _ = self.compute_padding(
+            input_data,
+            self.grid.time_step,
+            freq_window_tuple=freq_window_tuple,
+            fft_num_bins_in_window=fft_num_bins_in_window,
+            fft_bin_freq_resolution=fft_bin_freq_resolution,
+        )
+
+        input_data = bd.pad(input_data, (0, required_padding), "edge")
+
+        spectrum = bd.fft(input_data)
+
+        spectrum_freqs, begin_freq_idx, end_freq_idx = self.compute_frequencies(
+            input_data.shape[0],
+            self.grid.time_step,
+            freq_window_tuple=freq_window_tuple,
+        )
+
+        return (
+            spectrum_freqs[begin_freq_idx:end_freq_idx],
+            spectrum[begin_freq_idx:end_freq_idx],
+        )
+
+    def impedance(
+        self,
+        freq_window_tuple=None,
+        fft_num_bins_in_window=None,
+        fft_bin_freq_resolution=None,
+    ):
+        """
+        Takes a single "node", a current and voltage record. The form of:
+        SoftArbitraryPointSource or tuple.
+        """
+        if self.grid.time_steps_passed == 0:
+            return [], []
+
+        if isinstance(self.objs, SoftArbitraryPointSource):
+            voltage_array = bd.array(self.objs.source_voltage)
+            current_array = bd.array(
+                self.objs.current_detector.I
+            )  # FIXME: this definitely isn't right
+
+        elif (
+            isinstance(self.objs, tuple)
+            and isinstance(self.objs[0], (BlockDetector, LineDetector))
+            and isinstance(self.objs[1], CurrentDetector)
+        ):
+            # FIXME:
+            voltage_array = bd.array(self.objs[0].E)[:][0, 0, 0]
+            current_array = bd.array(self.objs[1].I)
+        else:
+            raise ValueError("Sorry, FFT can't yet interpret the argument given.")
+
+        required_padding, _ = self.compute_padding(
+            voltage_array,
+            self.grid.time_step,
+            freq_window_tuple=freq_window_tuple,
+            fft_num_bins_in_window=fft_num_bins_in_window,
+            fft_bin_freq_resolution=fft_bin_freq_resolution,
+        )
+
+        voltage_array = bd.reshape(
+            voltage_array, self.grid.time_steps_passed
+        )  # flatten
+        current_array = bd.reshape(current_array, self.grid.time_steps_passed)
+
+        voltage_array = bd.pad(voltage_array, (0, required_padding), "edge")
+        current_array = bd.pad(current_array, (0, required_padding), "edge")
+
+        voltage_spectrum = bd.fft(voltage_array)
+        current_spectrum = bd.fft(current_array)
+
+        impedance_spectrum = bd.divide(
+            voltage_spectrum,
+            current_spectrum,
+            out=bd.zeros_like(voltage_spectrum),
+            where=current_spectrum != 0,
+        )
+
+        spectrum_freqs, begin_freq_idx, end_freq_idx = self.compute_frequencies(
+            voltage_array.shape[0],
+            self.grid.time_step,
+            freq_window_tuple=freq_window_tuple,
+        )
+
+        return (
+            spectrum_freqs[begin_freq_idx:end_freq_idx],
+            impedance_spectrum[begin_freq_idx:end_freq_idx],
+        )
+
+        #
+        # voltages = bd.pad(voltages, (0, required_length), 'edge')
+        # currents = bd.pad(currents, (0, required_length), 'edge')
+        #
+        # voltage_spectrum = bd.fft(voltages)
+        # current_spectrum = bd.fft(currents)
+        #
+        # spectrum_freqs, begin_freq_idx, end_freq_idx = \
+        #                         compute_frequencies(length_with_padding, dt, freq_window_tuple=None)
+        #
+        # spectrum_freqs[begin_freq:end_freq]
+
+    def plot_impedance(
+        self,
+        freq_window_tuple=None,
+        fft_num_bins_in_window=None,
+        fft_bin_freq_resolution=None,
+    ):
+        """
+        Frequencies are in Hz.
+        """
+
+        plt.plot(times_padded, voltages)
+
+        plt.plot(times_padded, currents)
+        # plt.plot(, abs(voltage_spectrum[begin_freq:end_freq]), label="volt")
+        plt.plot(
+            spectrum_freqs[begin_freq:end_freq],
+            abs(current_spectrum[begin_freq:end_freq]),
+            label="curr",
+        )
+
+        plt.figure()
+        #
+        # Z0 = scipy.constants.physical_constants['characteristic impedance of vacuum'][0]
+
+        impedance_spectrum = abs(voltage_spectrum / current_spectrum)
+
+        plt.plot(
+            spectrum_freqs[begin_freq:end_freq], impedance_spectrum[begin_freq:end_freq]
+        )
+        # plt.plot(spectrum_freqs[begin_freq:end_freq],impedance_spectrum[begin_freq:end_freq])
+        plt.savefig("/tmp/impedance_spectrum.svg")
+        # # plt.plot(spectrum_freqs,(voltage_spectrum/current_spectrum))
+        # plt.plot(spectrum_freqs[begin_freq:end_freq],(voltage_spectrum[begin_freq:end_freq]/current_spectrum[begin_freq:end_freq]).real)
+        # plt.plot(spectrum_freqs[begin_freq:end_freq],(voltage_spectrum[begin_freq:end_freq]/current_spectrum[begin_freq:end_freq]).imag)
+
+        plt.show()
+        # power_spectrum = -1.0*((voltage_spectrum[begin_freq:end_freq]*np.conj(current_spectrum[begin_freq:end_freq])).real)
+        # power_spectrum /= np.linalg.norm(power_spectrum)
+        # plt.plot(spectrum_freqs[begin_freq:end_freq],power_spectrum)
diff --git a/nidn/fdtd/grid.py b/nidn/fdtd/grid.py
new file mode 100644
index 0000000..dd40551
--- /dev/null
+++ b/nidn/fdtd/grid.py
@@ -0,0 +1,501 @@
+""" The FDTD Grid
+
+The grid is the core of the FDTD Library. It is where everything comes
+together and where the biggest part of the calculations are done.
+
+"""
+
+## Imports
+
+# standard library
+import os
+from os import path, makedirs, chdir, remove
+from subprocess import check_call, CalledProcessError
+from glob import glob
+from datetime import datetime
+
+# 3rd party
+from tqdm import tqdm
+from numpy import savez
+
+from ..utils.global_constants import SPEED_OF_LIGHT
+
+# typing
+from .typing_ import Tuple, Number, Tensorlike
+
+# relative
+from .backend import backend as bd
+
+## Functions
+def curl_E(E: Tensorlike) -> Tensorlike:
+    """Transforms an E-type field into an H-type field by performing a curl
+    operation
+
+    Args:
+        E: Electric field to take the curl of (E-type field located on the
+           edges of the grid cell [integer gridpoints])
+
+    Returns:
+        The curl of E (H-type field located on the faces of the grid [half-integer grid points])
+    """
+    curl = bd.zeros(E.shape)
+
+    curl[:, :-1, :, 0] += E[:, 1:, :, 2] - E[:, :-1, :, 2]
+    curl[:, :, :-1, 0] -= E[:, :, 1:, 1] - E[:, :, :-1, 1]
+
+    curl[:, :, :-1, 1] += E[:, :, 1:, 0] - E[:, :, :-1, 0]
+    curl[:-1, :, :, 1] -= E[1:, :, :, 2] - E[:-1, :, :, 2]
+
+    curl[:-1, :, :, 2] += E[1:, :, :, 1] - E[:-1, :, :, 1]
+    curl[:, :-1, :, 2] -= E[:, 1:, :, 0] - E[:, :-1, :, 0]
+
+    return curl
+
+
+def curl_H(H: Tensorlike) -> Tensorlike:
+    """Transforms an H-type field into an E-type field by performing a curl
+    operation
+
+    Args:
+        H: Magnetic field to take the curl of (H-type field located on half-integer grid points)
+
+    Returns:
+        The curl of H (E-type field located on the edges of the grid [integer grid points])
+
+    """
+    curl = bd.zeros(H.shape)
+
+    curl[:, 1:, :, 0] += H[:, 1:, :, 2] - H[:, :-1, :, 2]
+    curl[:, :, 1:, 0] -= H[:, :, 1:, 1] - H[:, :, :-1, 1]
+
+    curl[:, :, 1:, 1] += H[:, :, 1:, 0] - H[:, :, :-1, 0]
+    curl[1:, :, :, 1] -= H[1:, :, :, 2] - H[:-1, :, :, 2]
+
+    curl[1:, :, :, 2] += H[1:, :, :, 1] - H[:-1, :, :, 1]
+    curl[:, 1:, :, 2] -= H[:, 1:, :, 0] - H[:, :-1, :, 0]
+
+    return curl
+
+
+## FDTD Grid Class
+class Grid:
+    """The FDTD Grid
+
+    The grid is the core of the FDTD Library. It is where everything comes
+    together and where the biggest part of the calculations are done.
+
+    """
+
+    from .visualization import visualize
+
+    def __init__(
+        self,
+        shape: Tuple[Number, Number, Number],
+        grid_spacing: float = 155e-9,
+        permittivity: float = 1.0,
+        permeability: float = 1.0,
+        courant_number: float = None,
+    ):
+        """
+        Args:
+            shape: shape of the FDTD grid.
+            grid_spacing: distance between the grid cells.
+            permittivity: the relative permittivity of the background.
+            permeability: the relative permeability of the background.
+            courant_number: the courant number of the FDTD simulation.
+                Defaults to the inverse of the square root of the number of
+                dimensions > 1 (optimal value). The timestep of the simulation
+                will be derived from this number using the CFL-condition.
+        """
+        # save the grid spacing
+        self.grid_spacing = float(grid_spacing)
+
+        # save grid shape as integers
+        self.Nx, self.Ny, self.Nz = self._handle_tuple(shape)
+
+        # dimension of the simulation:
+        self.D = int(self.Nx > 1) + int(self.Ny > 1) + int(self.Nz > 1)
+
+        # courant number of the simulation (optimal value)
+        max_courant_number = float(self.D) ** (-0.5)
+        if courant_number is None:
+            # slight stability factor added
+            self.courant_number = 0.99 * max_courant_number
+        elif courant_number > max_courant_number:
+            raise ValueError(
+                f"courant_number {courant_number} too high for "
+                f"a {self.D}D simulation"
+            )
+        else:
+            self.courant_number = float(courant_number)
+
+        # timestep of the simulation
+        self.time_step = self.courant_number * self.grid_spacing / SPEED_OF_LIGHT
+
+        # save electric and magnetic field
+        self.E = bd.zeros((self.Nx, self.Ny, self.Nz, 3))
+        self.H = bd.zeros((self.Nx, self.Ny, self.Nz, 3))
+
+        # save the inverse of the relative permittiviy and the relative permeability
+        # these tensors can be anisotropic!
+
+        if bd.is_array(permittivity) and len(permittivity.shape) == 3:
+            permittivity = permittivity[:, :, :, None]
+        self.inverse_permittivity = bd.ones((self.Nx, self.Ny, self.Nz, 3)) / float(
+            permittivity
+        )
+
+        if bd.is_array(permeability) and len(permeability.shape) == 3:
+            permeability = permeability[:, :, :, None]
+        self.inverse_permeability = bd.ones((self.Nx, self.Ny, self.Nz, 3)) / float(
+            permeability
+        )
+
+        # save current time index
+        self.time_steps_passed = 0
+
+        # dictionary containing the sources:
+        self.sources = []
+
+        # dictionary containing the boundaries
+        self.boundaries = []
+
+        # dictionary containing the detectors
+        self.detectors = []
+
+        # dictionary containing the objects in the grid
+        self.objects = []
+
+        # folder path to store the simulation
+        self.folder = None
+
+    def _handle_distance(self, distance: Number) -> int:
+        """transform a distance to an integer number of gridpoints"""
+        if not isinstance(distance, int):
+            return int(float(distance) / self.grid_spacing + 0.5)
+        return distance
+
+    def _handle_time(self, time: Number) -> int:
+        """transform a time value to an integer number of timesteps"""
+        if not isinstance(time, int):
+            return int(float(time) / self.time_step + 0.5)
+        return time
+
+    def _handle_tuple(
+        self, shape: Tuple[Number, Number, Number]
+    ) -> Tuple[int, int, int]:
+        """validate the grid shape and transform to a length-3 tuple of ints"""
+        if len(shape) != 3:
+            raise ValueError(
+                f"invalid grid shape {shape}\n"
+                f"grid shape should be a 3D tuple containing floats or ints"
+            )
+        x, y, z = shape
+        x = self._handle_distance(x)
+        y = self._handle_distance(y)
+        z = self._handle_distance(z)
+        return x, y, z
+
+    def _handle_slice(self, s: slice) -> slice:
+        """validate the slice and transform possibly float values to ints"""
+        start = (
+            s.start
+            if not isinstance(s.start, float)
+            else self._handle_distance(s.start)
+        )
+        stop = (
+            s.stop if not isinstance(s.stop, float) else self._handle_distance(s.stop)
+        )
+        step = (
+            s.step if not isinstance(s.step, float) else self._handle_distance(s.step)
+        )
+        return slice(start, stop, step)
+
+    def _handle_single_key(self, key):
+        """transform a single index key to a slice or list"""
+        try:
+            len(key)
+            return [self._handle_distance(k) for k in key]
+        except TypeError:
+            if isinstance(key, slice):
+                return self._handle_slice(key)
+            else:
+                return [self._handle_distance(key)]
+        return key
+
+    @property
+    def x(self) -> int:
+        """get the number of grid cells in the x-direction"""
+        return self.Nx * self.grid_spacing
+
+    @property
+    def y(self) -> int:
+        """get the number of grid cells in the y-direction"""
+        return self.Ny * self.grid_spacing
+
+    @property
+    def z(self) -> int:
+        """get the number of grid cells in the y-direction"""
+        return self.Nz * self.grid_spacing
+
+    @property
+    def shape(self) -> Tuple[int, int, int]:
+        """get the shape of the FDTD grid"""
+        return (self.Nx, self.Ny, self.Nz)
+
+    @property
+    def time_passed(self) -> float:
+        """get the total time passed"""
+        return self.time_steps_passed * self.time_step
+
+    def run(self, total_time: Number, progress_bar: bool = True):
+        """run an FDTD simulation.
+
+        Args:
+            total_time: the total time for the simulation to run.
+            progress_bar: choose to show a progress bar during
+                simulation
+
+        """
+        if isinstance(total_time, float):
+            total_time /= self.time_step
+        time = range(0, int(total_time), 1)
+        if progress_bar:
+            time = tqdm(time)
+        for _ in time:
+            self.step()
+
+    def step(self):
+        """do a single FDTD step by first updating the electric field and then
+        updating the magnetic field
+        """
+        self.update_E()
+        self.update_H()
+        self.time_steps_passed += 1
+
+    def update_E(self):
+        """update the electric field by using the curl of the magnetic field"""
+
+        # update boundaries: step 1
+        for boundary in self.boundaries:
+            boundary.update_phi_E()
+
+        curl = curl_H(self.H)
+        self.E += self.courant_number * self.inverse_permittivity * curl
+
+        # update objects
+        for obj in self.objects:
+            obj.update_E(curl)
+
+        # update boundaries: step 2
+        for boundary in self.boundaries:
+            boundary.update_E()
+
+        # add sources to grid:
+        for src in self.sources:
+            src.update_E()
+
+        # detect electric field
+        for det in self.detectors:
+            det.detect_E()
+
+    def update_H(self):
+        """update the magnetic field by using the curl of the electric field"""
+
+        # update boundaries: step 1
+        for boundary in self.boundaries:
+            boundary.update_phi_H()
+
+        curl = curl_E(self.E)
+        self.H -= self.courant_number * self.inverse_permeability * curl
+
+        # update objects
+        for obj in self.objects:
+            obj.update_H(curl)
+
+        # update boundaries: step 2
+        for boundary in self.boundaries:
+            boundary.update_H()
+
+        # add sources to grid:
+        for src in self.sources:
+            src.update_H()
+
+        # detect electric field
+        for det in self.detectors:
+            det.detect_H()
+
+    def reset(self):
+        """reset the grid by setting all fields to zero"""
+        self.H *= 0.0
+        self.E *= 0.0
+        self.time_steps_passed *= 0
+
+    def add_source(self, name, source):
+        """add a source to the grid"""
+        source._register_grid(self)
+        self.sources[name] = source
+
+    def add_boundary(self, name, boundary):
+        """add a boundary to the grid"""
+        boundary._register_grid(self)
+        self.boundaries[name] = boundary
+
+    def add_detector(self, name, detector):
+        """add a detector to the grid"""
+        detector._register_grid(self)
+        self.detectors[name] = detector
+
+    def add_object(self, name, obj):
+        """add an object to the grid"""
+        obj._register_grid(self)
+        self.objects[name] = obj
+
+    def __setitem__(self, key, attr):
+        if not isinstance(key, tuple):
+            x, y, z = key, slice(None), slice(None)
+        elif len(key) == 1:
+            x, y, z = key[0], slice(None), slice(None)
+        elif len(key) == 2:
+            x, y, z = key[0], key[1], slice(None)
+        elif len(key) == 3:
+            x, y, z = key
+        else:
+            raise KeyError("maximum number of indices for the grid is 3")
+
+        attr._register_grid(
+            grid=self,
+            x=self._handle_single_key(x),
+            y=self._handle_single_key(y),
+            z=self._handle_single_key(z),
+        )
+
+    def __repr__(self):
+        return (
+            f"{self.__class__.__name__}(shape=({self.Nx},{self.Ny},{self.Nz}), "
+            f"grid_spacing={self.grid_spacing:.2e}, courant_number={self.courant_number:.2f})"
+        )
+
+    def __str__(self):
+        """string representation of the grid
+
+        lists all the components and their locations in the grid.
+        """
+        s = repr(self) + "\n"
+        if self.sources:
+            s = s + "\nsources:\n"
+            for src in self.sources:
+                s += str(src)
+        if self.detectors:
+            s = s + "\ndetectors:\n"
+            for det in self.detectors:
+                s += str(det)
+        if self.boundaries:
+            s = s + "\nboundaries:\n"
+            for bnd in self.boundaries:
+                s += str(bnd)
+        if self.objects:
+            s = s + "\nobjects:\n"
+            for obj in self.objects:
+                s += str(obj)
+        return s
+
+    def save_simulation(self, sim_name=None):
+        """
+        Creates a folder and initializes environment to store simulation or related details.
+        saveSimulation() needs to be run before running any function that stores data (generate_video(), save_data()).
+
+        Parameters:-
+            (optional) sim_name (string): Preferred name for simulation
+        """
+        makedirs("fdtd_output", exist_ok=True)  # Output master folder declaration
+        # making full_sim_name with timestamp
+        full_sim_name = (
+            str(datetime.now().year)
+            + "-"
+            + str(datetime.now().month)
+            + "-"
+            + str(datetime.now().day)
+            + "-"
+            + str(datetime.now().hour)
+            + "-"
+            + str(datetime.now().minute)
+            + "-"
+            + str(datetime.now().second)
+        )
+        # Simulation name (optional)
+        if sim_name is not None:
+            full_sim_name = full_sim_name + " (" + sim_name + ")"
+        folder = "fdtd_output_" + full_sim_name
+        # storing folder path for saving simulation
+        self.folder = os.path.abspath(path.join("fdtd_output", folder))
+        # storing timestamp title for self.generate_video
+        self.full_sim_name = full_sim_name
+        makedirs(self.folder, exist_ok=True)
+        return self.folder
+
+    def generate_video(self, delete_frames=False):
+        """Compiles frames into a video
+
+        These framed should be saved through ``fdtd.Grid.visualize(save=True)`` while having ``fdtd.Grid.save_simulation()`` enabled.
+
+        Args:
+            delete_frames (optional, bool): delete stored frames after conversion to video.
+
+        Returns:
+            the filename of the generated video.
+
+        Note:
+            this function requires ``ffmpeg`` to be available in your path.
+        """
+        if self.folder is None:
+            raise Exception(
+                "Save location not initialized. Please read about 'fdtd.Grid.saveSimulation()' or try running 'grid.saveSimulation()'."
+            )
+        cwd = path.abspath(os.getcwd())
+        chdir(self.folder)
+        try:
+            check_call(
+                [
+                    "ffmpeg",
+                    "-y",
+                    "-framerate",
+                    "8",
+                    "-i",
+                    "file%04d.png",
+                    "-r",
+                    "30",
+                    "-pix_fmt",
+                    "yuv420p",
+                    "fdtd_sim_video_" + self.full_sim_name + ".mp4",
+                ]
+            )
+        except (FileNotFoundError, CalledProcessError):
+            raise CalledProcessError(
+                "Error when calling ffmpeg. Is ffmpeg installed and available in your path?"
+            )
+        if delete_frames:  # delete frames
+            for file_name in glob("*.png"):
+                remove(file_name)
+        video_path = path.abspath(
+            path.join(self.folder, f"fdtd_sim_video_{self.full_sim_name}.mp4")
+        )
+        chdir(cwd)
+        return video_path
+
+    def save_data(self):
+        """
+        Saves readings from all detectors in the grid into a numpy zip file. Each detector is stored in separate arrays. Electric and magnetic field field readings of each detector are also stored separately with suffix " (E)" and " (H)" (Example: ['detector0 (E)', 'detector0 (H)']). Therefore, the numpy zip file contains arrays twice the number of detectors.
+        REQUIRES 'fdtd.Grid.save_simulation()' to be run before this function.
+
+        Parameters: None
+        """
+        if self.folder is None:
+            raise Exception(
+                "Save location not initialized. Please read about 'fdtd.Grid.saveSimulation()' or try running 'grid.saveSimulation()'."
+            )
+        dic = {}
+        for detector in self.detectors:
+            dic[detector.name + " (E)"] = [x for x in detector.detector_values()["E"]]
+            dic[detector.name + " (H)"] = [x for x in detector.detector_values()["H"]]
+        savez(path.join(self.folder, "detector_readings"), **dic)
diff --git a/nidn/fdtd/objects.py b/nidn/fdtd/objects.py
new file mode 100644
index 0000000..9b91fca
--- /dev/null
+++ b/nidn/fdtd/objects.py
@@ -0,0 +1,271 @@
+""" The objects to place in the grid.
+
+Objects define all the regions in the grid with a modified update equation,
+such as for example regions with anisotropic permittivity etc.
+
+Available Objects:
+ - Object
+ - AnisotropicObject
+
+"""
+
+## Imports
+
+# typing
+from ..utils.global_constants import ETA_0
+from .typing_ import Tensorlike, ListOrSlice
+
+# relative
+from .grid import Grid
+from .backend import backend as bd
+
+
+## Object
+class Object:
+    """An object to place in the grid"""
+
+    def __init__(self, permittivity: Tensorlike, name: str = None):
+        """
+        Args:
+            permittivity: permittivity tensor
+            name: name of the object (will become available as attribute to the grid)
+        """
+        self.grid = None
+        self.name = name
+        self.permittivity = permittivity
+
+    def _register_grid(
+        self, grid: Grid, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ):
+        """Register the object to the grid
+
+        Args:
+            grid: the grid to register the object into
+            x: the x-location of the object in the grid
+            y: the y-location of the object in the grid
+            z: the z-location of the object in the grid
+        """
+        self.grid = grid
+        self.grid.objects.append(self)
+        if self.name is not None:
+            if not hasattr(grid, self.name):
+                setattr(grid, self.name, self)
+            else:
+                raise ValueError(
+                    f"The grid already has an attribute with name {self.name}"
+                )
+        self.x = self._handle_slice(x, max_index=self.grid.Nx)
+        self.y = self._handle_slice(y, max_index=self.grid.Ny)
+        self.z = self._handle_slice(z, max_index=self.grid.Nz)
+
+        self.Nx = abs(self.x.stop - self.x.start)
+        self.Ny = abs(self.y.stop - self.y.start)
+        self.Nz = abs(self.z.stop - self.z.start)
+
+        # set the permittivity of the object
+        if bd.is_array(self.permittivity) and len(self.permittivity.shape) == 3:
+            self.permittivity = self.permittivity[:, :, :, None]
+        self.inverse_permittivity = (
+            bd.ones((self.Nx, self.Ny, self.Nz, 3)) / self.permittivity
+        )
+
+        # set the permittivity values of the object at its border to be equal
+        # to the grid permittivity. This way, the object is made symmetric.
+        if self.Nx > 1:
+            self.inverse_permittivity[-1, :, :, 0] = self.grid.inverse_permittivity[
+                -1, self.y, self.z, 0
+            ]
+        if self.Ny > 1:
+            self.inverse_permittivity[:, -1, :, 1] = self.grid.inverse_permittivity[
+                self.x, -1, self.z, 1
+            ]
+        if self.Nz > 1:
+            self.inverse_permittivity[:, :, -1, 2] = self.grid.inverse_permittivity[
+                self.x, self.y, -1, 2
+            ]
+
+        self.grid.inverse_permittivity[self.x, self.y, self.z] = 0
+
+    def _handle_slice(self, s: ListOrSlice, max_index: int = None) -> slice:
+        if isinstance(s, list):
+            if len(s) == 1:
+                return slice(s[0], s[0] + 1, None)
+            raise IndexError(
+                "One can only use slices or single indices to index the grid for an Object"
+            )
+        if isinstance(s, slice):
+            start, stop, step = s.start, s.stop, s.step
+            if step is not None and step != 1:
+                raise IndexError(
+                    "Can only use slices with unit step to index the grid for an Object"
+                )
+            if start is None:
+                start = 0
+            if start < 0:
+                start = max_index + start
+            if stop is None:
+                stop = max_index
+            if stop < 0:
+                stop = max_index + stop
+            return slice(start, stop, None)
+        raise ValueError("Invalid grid indexing used for object")
+
+    def update_E(self, curl_H):
+        """custom update equations for inside the object
+
+        Args:
+            curl_H: the curl of magnetic field in the grid.
+
+        """
+        loc = (self.x, self.y, self.z)
+        self.grid.E[loc] += (
+            self.grid.courant_number * self.inverse_permittivity * curl_H[loc]
+        )
+
+    def update_H(self, curl_E):
+        """custom update equations for inside the object
+
+        Args:
+            curl_E: the curl of electric field in the grid.
+
+        """
+
+    def __repr__(self):
+        return f"{self.__class__.__name__}(name={repr(self.name)})"
+
+    def __str__(self):
+        s = "    " + repr(self) + "\n"
+
+        def _handle_slice(s):
+            return (
+                str(s)
+                .replace("slice(", "")
+                .replace(")", "")
+                .replace(", ", ":")
+                .replace("None", "")
+            )
+
+        x = _handle_slice(self.x)
+        y = _handle_slice(self.y)
+        z = _handle_slice(self.z)
+        s += f"        @ x={x}, y={y}, z={z}".replace(":,", ",")
+        if s[-1] == ":":
+            s = s[:-1]
+        return s + "\n"
+
+
+class AbsorbingObject(Object):
+    """An absorbing object takes conductivity into account"""
+
+    def __init__(
+        self, permittivity: Tensorlike, conductivity: Tensorlike, name: str = None
+    ):
+        """
+        Args:
+            permittivity: permittivity tensor
+            conductivity: conductivity tensor (will introduce the loss)
+            name: name of the object (will become available as attribute to the grid)
+        """
+        super().__init__(permittivity, name)
+        self.conductivity = conductivity
+
+    def _register_grid(
+        self, grid: Grid, x: slice = None, y: slice = None, z: slice = None
+    ):
+        """Register a grid to the object
+
+        Args:
+            grid: the grid to register the object into
+            x: the x-location of the object in the grid
+            y: the y-location of the object in the grid
+            z: the z-location of the object in the grid
+        """
+        super()._register_grid(grid=grid, x=x, y=y, z=z)
+
+        conductivity = bd.asarray(self.conductivity)
+        while conductivity.ndim < self.inverse_permittivity.ndim:
+            conductivity = conductivity[..., None]
+        self.conductivity = bd.broadcast_to(
+            conductivity, self.inverse_permittivity.shape
+        )
+
+        self.absorption_factor = (
+            0.5
+            * self.grid.courant_number
+            * self.inverse_permittivity
+            * self.conductivity
+            * self.grid.grid_spacing
+            * ETA_0
+        )
+
+    def update_E(self, curl_H):
+        """custom update equations for inside the absorbing object
+
+        Args:
+            curl_H: the curl of magnetic field in the grid.
+
+        """
+        loc = (self.x, self.y, self.z)
+        self.grid.E[loc] *= (1 - self.absorption_factor) / (1 + self.absorption_factor)
+        self.grid.E[loc] += (
+            self.grid.courant_number
+            * self.inverse_permittivity
+            * curl_H[loc]
+            / (1 + self.absorption_factor)
+        )
+
+    def update_H(self, curl_E):
+        """custom update equations for inside the absorbing object
+
+        Args:
+            curl_E: the curl of electric field in the grid.
+
+        """
+
+
+class AnisotropicObject(Object):
+    """An object with anisotropic permittivity tensor"""
+
+    def _register_grid(
+        self, grid: Grid, x: slice = None, y: slice = None, z: slice = None
+    ):
+        """Register a grid to the object
+
+        Args:
+            grid: the grid to register the object into
+            x: the x-location of the object in the grid
+            y: the y-location of the object in the grid
+            z: the z-location of the object in the grid
+        """
+        super()._register_grid(grid=grid, x=x, y=y, z=z)
+        eye = bd.zeros((self.Nx * self.Ny * self.Nz, 3, 3))
+        eye[:, range(3), range(3)] = 1.0
+        self.inverse_permittivity = bd.reshape(
+            bd.reshape(self.inverse_permittivity, (-1, 1, 3)) * eye,
+            (self.Nx, self.Ny, self.Nz, 3, 3),
+        )
+
+    def update_E(self, curl_H):
+        """custom update equations for inside the anisotropic object
+
+        Args:
+            curl_H: the curl of magnetic field in the grid.
+
+        """
+        loc = (self.x, self.y, self.z)
+        self.grid.E[loc] += bd.reshape(
+            self.grid.courant_number
+            * bd.bmm(
+                bd.reshape(self.inverse_permittivity, (-1, 3, 3)),
+                bd.reshape(curl_H[loc], (-1, 3, 1)),
+            ),
+            (self.Nx, self.Ny, self.Nz, 3),
+        )
+
+    def update_H(self, curl_E):
+        """custom update equations for inside the anisotropic object
+
+        Args:
+            curl_E: the curl of electric field in the grid.
+
+        """
diff --git a/nidn/fdtd/sources.py b/nidn/fdtd/sources.py
new file mode 100644
index 0000000..bc2e003
--- /dev/null
+++ b/nidn/fdtd/sources.py
@@ -0,0 +1,642 @@
+""" Sources are objects that inject the fields into the grid.
+
+Available sources:
+
+- PointSource
+- LineSource
+
+"""
+## Imports
+
+# other
+from math import pi, sin
+
+# typing
+from .typing_ import Tuple, Number, ListOrSlice, List
+from numpy import ndarray
+
+# relatvie
+from .grid import Grid
+from .backend import backend as bd
+from .waveforms import *
+from .detectors import CurrentDetector
+
+## PointSource class
+class PointSource:
+    """A source placed at a single point (grid cell) in the grid"""
+
+    def __init__(
+        self,
+        period: Number = 15,
+        amplitude: float = 1.0,
+        phase_shift: float = 0.0,
+        name: str = None,
+        pulse: bool = False,
+        cycle: int = 5,
+        hanning_dt: float = 10.0,
+    ):
+        """Create a LineSource with a gaussian profile
+
+        Args:
+            period: The period of the source. The period can be specified
+                as integer [timesteps] or as float [seconds]
+            amplitude: The electric field amplitude in simulation units
+            phase_shift: The phase offset of the source.
+            name: name of the source.
+            pulse: Set True to use a Hanning window pulse instead of continuous wavefunction.
+            cycle: cycles for Hanning window pulse.
+            hanning_dt: timestep used for Hanning window pulse width (optional).
+
+        """
+        self.grid = None
+        self.period = period
+        self.amplitude = amplitude
+        self.phase_shift = phase_shift
+        self.name = name
+        self.pulse = pulse
+        self.cycle = cycle
+        self.frequency = 1.0 / period
+        self.hanning_dt = hanning_dt if hanning_dt is not None else 0.5 / self.frequency
+
+    def _register_grid(self, grid: Grid, x: Number, y: Number, z: Number):
+        """Register a grid for the source.
+
+        Args:
+            grid: the grid to place the source into.
+            x: The x-location of the source in the grid
+            y: The y-location of the source in the grid
+            z: The z-location of the source in the grid
+
+        Note:
+            As its name suggests, this source is a POINT source.
+            Hence it should be placed at a single coordinate tuple
+            int the grid.
+        """
+        self.grid = grid
+        self.grid.sources.append(self)
+        if self.name is not None:
+            if not hasattr(grid, self.name):
+                setattr(grid, self.name, self)
+            else:
+                raise ValueError(
+                    f"The grid already has an attribute with name {self.name}"
+                )
+
+        try:
+            (x,), (y,), (z,) = x, y, z
+        except (TypeError, ValueError):
+            raise ValueError("a point source should be placed on a single grid cell.")
+        self.x, self.y, self.z = grid._handle_tuple((x, y, z))
+        self.period = grid._handle_time(self.period)
+
+    def update_E(self):
+        """Add the source to the electric field"""
+        q = self.grid.time_steps_passed
+        # if pulse
+        if self.pulse:
+            t1 = int(2 * pi / (self.frequency * self.hanning_dt / self.cycle))
+            if q < t1:
+                src = self.amplitude * hanning(
+                    self.frequency, q * self.hanning_dt, self.cycle
+                )
+            else:
+                # src = - self.grid.E[self.x, self.y, self.z, 2]
+                src = 0
+        # if not pulse
+        else:
+            src = self.amplitude * sin(2 * pi * q / self.period + self.phase_shift)
+        self.grid.E[self.x, self.y, self.z, 2] += src
+
+    def update_H(self):
+        """Add the source to the magnetic field"""
+
+    def __repr__(self):
+        return (
+            f"{self.__class__.__name__}(period={self.period}, "
+            f"amplitude={self.amplitude}, phase_shift={self.phase_shift}, "
+            f"name={repr(self.name)})"
+        )
+
+    def __str__(self):
+        s = "    " + repr(self) + "\n"
+        x = f"{self.x}"
+        y = f"{self.y}"
+        z = f"{self.z}"
+        s += f"        @ x={x}, y={y}, z={z}\n"
+        return s
+
+
+## LineSource class
+class LineSource:
+    """A source along a line in the FDTD grid"""
+
+    def __init__(
+        self,
+        period: Number = 15,
+        amplitude: float = 1.0,
+        phase_shift: float = 0.0,
+        name: str = None,
+        pulse: bool = False,
+        cycle: int = 5,
+        hanning_dt: float = 10.0,
+    ):
+        """Create a LineSource with a gaussian profile
+
+        Args:
+            period: The period of the source. The period can be specified
+                as integer [timesteps] or as float [seconds]
+            amplitude: The amplitude of the source in simulation units
+            phase_shift: The phase offset of the source.
+            pulse: Set True to use a Hanning window pulse instead of continuous wavefunction.
+            cycle: cycles for Hanning window pulse.
+            hanning_dt: timestep used for Hanning window pulse width (optional).
+
+        """
+        self.grid = None
+        self.period = period
+        self.amplitude = amplitude
+        self.phase_shift = phase_shift
+        self.name = name
+        self.pulse = pulse
+        self.cycle = cycle
+        self.frequency = 1.0 / period
+        self.hanning_dt = hanning_dt if hanning_dt is not None else 0.5 / self.frequency
+
+    def _register_grid(
+        self, grid: Grid, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ):
+        """Register a grid for the source.
+
+        Args:
+            grid: the grid to place the source into.
+            x: The x-location of the source in the grid
+            y: The y-location of the source in the grid
+            z: The z-location of the source in the grid
+
+        Note:
+            As its name suggests, this source is a LINE source.
+            Hence the source spans the diagonal of the cube
+            defined by the slices in the grid.
+        """
+        self.grid = grid
+        self.grid.sources.append(self)
+        if self.name is not None:
+            if not hasattr(grid, self.name):
+                setattr(grid, self.name, self)
+            else:
+                raise ValueError(
+                    f"The grid already has an attribute with name {self.name}"
+                )
+
+        self.x, self.y, self.z = self._handle_slices(x, y, z)
+
+        self.period = grid._handle_time(self.period)
+
+        L = len(self.x)
+        vect = bd.array(
+            (bd.array(self.x) - self.x[L // 2]) ** 2
+            + (bd.array(self.y) - self.y[L // 2]) ** 2
+            + (bd.array(self.z) - self.z[L // 2]) ** 2,
+            bd.float,
+        )
+
+        self.profile = bd.exp(-(vect**2) / (2 * (0.5 * vect.max()) ** 2))
+        self.profile /= self.profile.sum()
+        self.profile *= self.amplitude
+
+    def _handle_slices(
+        self, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ) -> Tuple[List, List, List]:
+        """Convert slices in the grid to lists
+
+        This is necessary to make the source span the diagonal of the volume
+        defined by the slices.
+
+        Args:
+            x: The x-location of the volume in the grid
+            y: The y-location of the volume in the grid
+            z: The z-location of the volume in the grid
+
+        Returns:
+            x, y, z: the x, y and z coordinates of the source as lists
+
+        """
+
+        # if list-indices were chosen:
+        if isinstance(x, list) and isinstance(y, list) and isinstance(z, list):
+            if len(x) != len(y) or len(y) != len(z) or len(z) != len(x):
+                raise IndexError(
+                    "sources require grid to be indexed with slices or equal length list-indices"
+                )
+            x = [self.grid._handle_distance(_x) for _x in x]
+            y = [self.grid._handle_distance(_y) for _y in y]
+            z = [self.grid._handle_distance(_z) for _z in z]
+            return x, y, z
+
+        # if a combination of list-indices and slices were chosen,
+        # convert the list-indices to slices.
+        # TODO: maybe issue a warning here?
+        if isinstance(x, list):
+            x = slice(
+                self.grid._handle_distance(x[0]),
+                self.grid._handle_distance(x[-1]),
+                None,
+            )
+        if isinstance(y, list):
+            y = slice(
+                self.grid._handle_distance(y[0]),
+                self.grid._handle_distance(y[-1]),
+                None,
+            )
+        if isinstance(z, list):
+            z = slice(
+                self.grid._handle_distance(z[0]),
+                self.grid._handle_distance(z[-1]),
+                None,
+            )
+
+        # if we get here, we can assume slices:
+        x0 = self.grid._handle_distance(x.start if x.start is not None else 0)
+        y0 = self.grid._handle_distance(y.start if y.start is not None else 0)
+        z0 = self.grid._handle_distance(z.start if z.start is not None else 0)
+        x1 = self.grid._handle_distance(x.stop if x.stop is not None else self.grid.Nx)
+        y1 = self.grid._handle_distance(y.stop if y.stop is not None else self.grid.Ny)
+        z1 = self.grid._handle_distance(z.stop if z.stop is not None else self.grid.Nz)
+
+        # we can now convert these coordinates into index lists
+        m = max(abs(x1 - x0), abs(y1 - y0), abs(z1 - z0))
+        if m < 2:
+            raise ValueError("a LineSource should consist of at least two gridpoints")
+        x = [v.item() for v in bd.array(bd.linspace(x0, x1, m, endpoint=False), bd.int)]
+        y = [v.item() for v in bd.array(bd.linspace(y0, y1, m, endpoint=False), bd.int)]
+        z = [v.item() for v in bd.array(bd.linspace(z0, z1, m, endpoint=False), bd.int)]
+
+        return x, y, z
+
+    def update_E(self):
+        """Add the source to the electric field"""
+        q = self.grid.time_steps_passed
+        # if pulse
+        if self.pulse:
+            t1 = int(2 * pi / (self.frequency * self.hanning_dt / self.cycle))
+            if q < t1:
+                vect = self.profile * hanning(
+                    self.frequency, q * self.hanning_dt, self.cycle
+                )
+            else:
+                # src = - self.grid.E[self.x, self.y, self.z, 2]
+                vect = self.profile * 0
+        # if not pulse
+        else:
+            vect = self.profile * sin(2 * pi * q / self.period + self.phase_shift)
+        # do not use list indexing here, as this is much slower especially for torch backend
+        # DISABLED: self.grid.E[self.x, self.y, self.z, 2] = vect
+        for x, y, z, value in zip(self.x, self.y, self.z, vect):
+            self.grid.E[x, y, z, 2] += value
+
+    def update_H(self):
+        """Add the source to the magnetic field"""
+
+    def __repr__(self):
+        return (
+            f"{self.__class__.__name__}(period={self.period}, "
+            f"amplitude={self.amplitude}, phase_shift={self.phase_shift}, "
+            f"name={repr(self.name)})"
+        )
+
+    def __str__(self):
+        s = "    " + repr(self) + "\n"
+        x = f"[{self.x[0]}, ... , {self.x[-1]}]"
+        y = f"[{self.y[0]}, ... , {self.y[-1]}]"
+        z = f"[{self.z[0]}, ... , {self.z[-1]}]"
+        s += f"        @ x={x}, y={y}, z={z}\n"
+        return s
+
+
+## PlaneSource class
+class PlaneSource:
+    """A source along a plane in the FDTD grid"""
+
+    def __init__(
+        self,
+        period: Number = 15,
+        amplitude: float = 1.0,
+        phase_shift: float = 0.0,
+        name: str = None,
+        polarization: str = "z",
+    ):
+        """Create a PlaneSource.
+
+        Args:
+            period: The period of the source. The period can be specified
+                as integer [timesteps] or as float [seconds]
+            amplitude: The amplitude of the source in simulation units
+            phase_shift: The phase offset of the source.
+            polarization: Axis of E-field polarization ('x','y',or 'z')
+        """
+        self.grid = None
+        self.period = period
+        self.amplitude = amplitude
+        self.phase_shift = phase_shift
+        self.name = name
+        self.polarization = polarization
+
+    def _register_grid(
+        self, grid: Grid, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ):
+        """Register a grid for the source.
+
+        Args:
+            grid: the grid to place the source into.
+            x: The x-location of the source in the grid
+            y: The y-location of the source in the grid
+            z: The z-location of the source in the grid
+
+        Note:
+        As its name suggests, this source is a LINE source.
+            Hence the source spans the diagonal of the cube
+            defined by the slices in the grid.
+        """
+        self.grid = grid
+        self.grid.sources.append(self)
+        if self.name is not None:
+            if not hasattr(grid, self.name):
+                setattr(grid, self.name, self)
+            else:
+                raise ValueError(
+                    f"The grid already has an attribute with name {self.name}"
+                )
+
+        self.x, self.y, self.z = self._handle_slices(x, y, z)
+
+        self.period = grid._handle_time(self.period)
+
+        x = bd.arange(self.x.start, self.x.stop, 1) - (self.x.start + self.x.stop) // 2
+        y = bd.arange(self.y.start, self.y.stop, 1) - (self.y.start + self.y.stop) // 2
+        z = bd.arange(self.z.start, self.z.stop, 1) - (self.z.start + self.z.stop) // 2
+        xvec, yvec, zvec = bd.broadcast_arrays(
+            x[:, None, None], y[None, :, None], z[None, None, :]
+        )
+        _xvec = bd.array(xvec, float)
+        _yvec = bd.array(yvec, float)
+        _zvec = bd.array(zvec, float)
+
+        profile = bd.ones(_xvec.shape)
+        self.profile = self.amplitude * profile
+
+    def _handle_slices(
+        self, x: ListOrSlice, y: ListOrSlice, z: ListOrSlice
+    ) -> Tuple[List, List, List]:
+        """Validate slices and calculate center of plane
+
+        Args:
+            x: The x-location of the volume in the grid
+            y: The y-location of the volume in the grid
+            z: The z-location of the volume in the grid
+
+        Returns:
+            x, y, z: the x, y and z coordinates of the source as slices
+
+        """
+        # ensure all slices
+        if not isinstance(x, slice):
+            if isinstance(x, list):
+                (x,) = x
+            x = slice(
+                self.grid._handle_distance(x), self.grid._handle_distance(x) + 1, None
+            )
+        if not isinstance(y, slice):
+            if isinstance(y, list):
+                (y,) = y
+            y = slice(
+                self.grid._handle_distance(y), self.grid._handle_distance(y) + 1, None
+            )
+        if not isinstance(z, slice):
+            if isinstance(z, list):
+                (z,) = z
+            z = slice(
+                self.grid._handle_distance(z), self.grid._handle_distance(z) + 1, None
+            )
+
+        # if we get here, we can assume slices:
+        x0 = self.grid._handle_distance(x.start if x.start is not None else 0)
+        y0 = self.grid._handle_distance(y.start if y.start is not None else 0)
+        z0 = self.grid._handle_distance(z.start if z.start is not None else 0)
+        x1 = self.grid._handle_distance(x.stop if x.stop is not None else self.grid.Nx)
+        y1 = self.grid._handle_distance(y.stop if y.stop is not None else self.grid.Ny)
+        z1 = self.grid._handle_distance(z.stop if z.stop is not None else self.grid.Nz)
+
+        # make sure all slices have a start, stop and no step:
+        x = (
+            slice(x0, x1)
+            if x0 < x1
+            else (slice(x1, x0) if x0 > x1 else slice(x0, x0 + 1))
+        )
+        y = (
+            slice(y0, y1)
+            if y0 < y1
+            else (slice(y1, y0) if y0 > y1 else slice(y0, y0 + 1))
+        )
+        z = (
+            slice(z0, z1)
+            if z0 < z1
+            else (slice(z1, z0) if z0 > z1 else slice(z0, z0 + 1))
+        )
+
+        if [x.stop - x.start, y.stop - y.start, z.stop - z.start].count(0) > 0:
+            raise ValueError(
+                "Given location for PlaneSource results in slices of length 0!"
+            )
+        if [x.stop - x.start, y.stop - y.start, z.stop - z.start].count(1) == 0:
+            raise ValueError("Given location for PlaneSource is not a 2D plane!")
+        if [x.stop - x.start, y.stop - y.start, z.stop - z.start].count(1) > 1:
+            raise ValueError(
+                "Given location for PlaneSource should have no more than one dimension in which it's flat.\n"
+                "Use a LineSource for lower dimensional sources."
+            )
+
+        self._Epol = "xyz".index(self.polarization)
+        if (
+            (x.stop - x.start == 1 and self.polarization == "x")
+            or (y.stop - y.start == 1 and self.polarization == "y")
+            or (z.stop - z.start == 1 and self.polarization == "z")
+        ):
+            raise ValueError(
+                "PlaneSource cannot be polarized perpendicular to the orientation of the plane."
+            )
+        _Hpols = [(z, 1, 2), (z, 0, 2), (y, 0, 1)][self._Epol]
+        if _Hpols[0].stop - _Hpols[0].start == 1:
+            self._Hpol = _Hpols[1]
+        else:
+            self._Hpol = _Hpols[2]
+
+        return x, y, z
+
+    def update_E(self):
+        """Add the source to the electric field"""
+        q = self.grid.time_steps_passed
+        vect = self.profile * sin(2 * pi * q / self.period + self.phase_shift)
+        self.grid.E[self.x, self.y, self.z, self._Epol] = vect
+
+    def update_H(self):
+        """Add the source to the magnetic field"""
+        q = self.grid.time_steps_passed
+        vect = self.profile * sin(2 * pi * q / self.period + self.phase_shift)
+        self.grid.H[self.x, self.y, self.z, self._Hpol] = vect
+
+    def __repr__(self):
+        return (
+            f"{self.__class__.__name__}(period={self.period}, "
+            f"amplitude={self.amplitude}, phase_shift={self.phase_shift}, "
+            f"name={repr(self.name)}, polarization={repr(self.polarization)})"
+        )
+
+    def __str__(self):
+        s = "    " + repr(self) + "\n"
+        x = f"[{self.x.start}, ... , {self.x.stop}]"
+        y = f"[{self.y.start}, ... , {self.y.stop}]"
+        z = f"[{self.z.start}, ... , {self.z.stop}]"
+        s += f"        @ x={x}, y={y}, z={z}\n"
+        return s
+
+
+class SoftArbitraryPointSource:
+    """
+
+    A source placed at a single point (grid cell) in the grid.
+    This source is special: it's both a source and a detector.
+
+    Unlike the other sources, the input is a voltage, not an electric field.
+    (really? why? should we convert back and forth?)
+
+    For electrical measurements I've only needed a single-index source,
+    so I don't know how the volume/line sources above work.
+    We want the FFT function to operate over any detector.
+    Maybe all sources should take an arbitary waveform argument?
+
+    Each index in the *waveform* array represents 1 value at a timestep.
+
+    There are many different *geometries* of "equivalent sources".
+    The detector/source paradigm used in /fdtd might perhaps not correspond to this in an ideal
+    fashion.
+
+    It's not intuitively clear to me what a "soft" source would imply in the optical case, or what
+    impedance even means for a laser.
+
+    /fdtd/ seems to have found primary use in optical circles,
+    so the default Z should probably be 0.
+
+    "Whilst established for microwaves and electrical circuits,
+    this concept has only very recently been observed in the optical domain,
+    yet is not well defined or understood."[1]
+
+    [1]: Optical impedance of metallic nano-structures, M. Mazilu and K. Dholakia
+    https://doi.org/10.1364/OE.14.007709
+
+    [2]: http://www.gwoptics.org/learn/02_Plane_waves/01_Fabry_Perot_cavity/02_Impedance_matched.php
+
+    /\/\-
+    """
+
+    def __init__(
+        self, waveform_array: ndarray, name: str = None, impedance: float = 0.0
+    ):
+        """Create
+
+
+
+        Args:
+            waveform_array
+        """
+        self.grid = None
+        self.name = name
+        self.current_detector = None
+        self.waveform_array = waveform_array
+        self.impedance = impedance
+        self.input_voltage = []  # voltage hard-imposed by the source
+        self.source_voltage = []  #
+        # "field" rather than "voltage" might be more meaningful
+        # FIXME: these voltage time histories have a different dimensionality
+
+    def _register_grid(self, grid: Grid, x: Number, y: Number, z: Number):
+        """Register a grid for the source.
+
+        Args:
+            grid: the grid to place the source into.
+            x: The x-location of the source in the grid
+            y: The y-location of the source in the grid
+            z: The z-location of the source in the grid
+
+        Note:
+            As its name suggests, this source is a POINT source.
+            Hence it should be placed at a single coordinate tuple
+            int the grid.
+        """
+        self.grid = grid
+        self.grid.sources.append(self)
+        if self.name is not None:
+            if not hasattr(grid, self.name):
+                setattr(grid, self.name, self)
+            else:
+                raise ValueError(
+                    f"The grid already has an attribute with name {self.name}"
+                )
+
+        try:
+            (x,), (y,), (z,) = x, y, z
+        except (TypeError, ValueError):
+            raise ValueError("a point source should be placed on a single grid cell.")
+        self.x, self.y, self.z = grid._handle_tuple((x, y, z))
+
+        if self.name is not None:
+            detector_name += "_I"
+        else:
+            detector_name = None
+
+        self.current_detector = CurrentDetector(name=detector_name)
+        grid[x, y, z] = self.current_detector
+
+    def update_E(self):
+
+        # It is important that this step happen between the E-field update and the
+        # H-field update.
+
+        if self.grid.time_steps_passed < self.waveform_array.shape[0]:
+            # check for off-by-one error here
+            input_voltage = self.waveform_array[self.grid.time_steps_passed]
+        else:
+            input_voltage = 0.0  # one could taper the last value off smoothly instead
+
+        if self.grid.time_steps_passed > 0:
+            current = self.current_detector.I[-1][0][0][0]
+        else:
+            current = 0.0
+
+        if self.impedance > 0:
+            source_resistive_voltage = self.impedance * current
+            output_voltage = input_voltage + source_resistive_voltage
+        else:
+            output_voltage = input_voltage
+
+        # right now, this does not compensate for the cell's permittivity!
+
+        self.grid.E[self.x, self.y, self.z, 2] += (
+            output_voltage / self.grid.grid_spacing
+        )
+
+        self.input_voltage.append([[[input_voltage]]])
+        self.source_voltage.append([[[output_voltage]]])
+
+    def update_H(self):
+        pass
+
+    def __repr__(self):
+        return f"{self.__class__.__name__}()"
+
+    def __str__(self):
+        s = "    " + repr(self) + "\n"
+        x = f"{self.x}"
+        y = f"{self.y}"
+        z = f"{self.z}"
+        s += f"        @ x={x}, y={y}, z={z}\n"
+        return s
diff --git a/nidn/fdtd/typing_.py b/nidn/fdtd/typing_.py
new file mode 100644
index 0000000..c4becc0
--- /dev/null
+++ b/nidn/fdtd/typing_.py
@@ -0,0 +1,24 @@
+""" common types """
+
+## Standard Library Types
+from typing import Union, Tuple, List
+from numbers import Number
+
+## Numpy types
+from numpy import ndarray
+
+## Torch types
+try:
+    from torch import Tensor
+except ImportError:
+    Tensor = None
+
+## Backend types
+if Tensor is not None:
+    Tensorlike = Union[ndarray, Tensor]
+else:
+    Tensorlike = ndarray
+
+## Composite types
+ListOrSlice = Union[List[int], slice]
+IntOrSlice = Union[int, slice]
diff --git a/nidn/fdtd/visualization.py b/nidn/fdtd/visualization.py
new file mode 100644
index 0000000..50bb92d
--- /dev/null
+++ b/nidn/fdtd/visualization.py
@@ -0,0 +1,484 @@
+""" visualization methods for the fdtd Grid.
+
+This module supplies visualization methods for the FDTD Grid. They are
+imported by the Grid class and hence are available as Grid methods.
+
+"""
+
+## Imports
+import os
+
+# plotting
+import matplotlib.pyplot as plt
+import matplotlib.patches as ptc
+from matplotlib.colors import LogNorm
+
+# 3rd party
+from tqdm import tqdm
+from numpy import log10, where
+from scipy.signal import hilbert  # TODO: Write hilbert function to replace using scipy
+
+# relative
+from .backend import backend as bd
+
+
+# 2D visualization function
+
+
+def visualize(
+    grid,
+    x=None,
+    y=None,
+    z=None,
+    cmap="Blues",
+    pbcolor="C3",
+    pmlcolor=(0, 0, 0, 0.1),
+    objcolor=(1, 0, 0, 0.1),
+    srccolor="C0",
+    detcolor="C2",
+    norm="linear",
+    show=False,  # default False to allow animate to be true
+    animate=False,  # True to see frame by frame states of grid while running simulation
+    index=None,  # index for each frame of animation (visualize fn runs in a loop, loop variable is passed as index)
+    save=False,  # True to save frames (requires parameters index, folder)
+    folder=None,  # folder path to save frames
+):
+    """visualize a projection of the grid and the optical energy inside the grid
+
+    Args:
+        x: the x-value to make the yz-projection (leave None if using different projection)
+        y: the y-value to make the zx-projection (leave None if using different projection)
+        z: the z-value to make the xy-projection (leave None if using different projection)
+        cmap: the colormap to visualize the energy in the grid
+        pbcolor: the color to visualize the periodic boundaries
+        pmlcolor: the color to visualize the PML
+        objcolor: the color to visualize the objects in the grid
+        srccolor: the color to visualize the sources in the grid
+        detcolor: the color to visualize the detectors in the grid
+        norm: how to normalize the grid_energy color map ('linear' or 'log').
+        show: call pyplot.show() at the end of the function
+        animate: see frame by frame state of grid during simulation
+        index: index for each frame of animation (typically a loop variable is passed)
+        save: save frames in a folder
+        folder: path to folder to save frames
+    """
+    if norm not in ("linear", "lin", "log"):
+        raise ValueError("Color map normalization should be 'linear' or 'log'.")
+    # imports (placed here to circumvent circular imports)
+    from .sources import PointSource, LineSource, PlaneSource
+    from .boundaries import _PeriodicBoundaryX, _PeriodicBoundaryY, _PeriodicBoundaryZ
+    from .boundaries import (
+        _PMLXlow,
+        _PMLXhigh,
+        _PMLYlow,
+        _PMLYhigh,
+        _PMLZlow,
+        _PMLZhigh,
+    )
+
+    if animate:  # pause for 0.1s, clear plot
+        plt.pause(0.02)
+        plt.clf()
+        plt.ion()  # ionteration on for animation effect
+
+    # validate x, y and z
+    if x is not None:
+        if not isinstance(x, int):
+            raise ValueError("the `x`-location supplied should be a single integer")
+        if y is not None or z is not None:
+            raise ValueError(
+                "if an `x`-location is supplied, one should not supply a `y` or a `z`-location!"
+            )
+    elif y is not None:
+        if not isinstance(y, int):
+            raise ValueError("the `y`-location supplied should be a single integer")
+        if z is not None or x is not None:
+            raise ValueError(
+                "if a `y`-location is supplied, one should not supply a `z` or a `x`-location!"
+            )
+    elif z is not None:
+        if not isinstance(z, int):
+            raise ValueError("the `z`-location supplied should be a single integer")
+        if x is not None or y is not None:
+            raise ValueError(
+                "if a `z`-location is supplied, one should not supply a `x` or a `y`-location!"
+            )
+    else:
+        raise ValueError(
+            "at least one projection plane (x, y or z) should be supplied to visualize the grid!"
+        )
+
+    # just to create the right legend entries:
+    plt.plot([], lw=7, color=objcolor, label="Objects")
+    plt.plot([], lw=7, color=pmlcolor, label="PML")
+    plt.plot([], lw=3, color=pbcolor, label="Periodic Boundaries")
+    plt.plot([], lw=3, color=srccolor, label="Sources")
+    plt.plot([], lw=3, color=detcolor, label="Detectors")
+
+    # Grid energy
+    grid_energy = bd.sum(grid.E**2 + grid.H**2, -1)
+    if x is not None:
+        assert grid.Ny > 1 and grid.Nz > 1
+        xlabel, ylabel = "y", "z"
+        Nx, Ny = grid.Ny, grid.Nz
+        pbx, pby = _PeriodicBoundaryY, _PeriodicBoundaryZ
+        pmlxl, pmlxh, pmlyl, pmlyh = _PMLYlow, _PMLYhigh, _PMLZlow, _PMLZhigh
+        grid_energy = grid_energy[x, :, :]
+    elif y is not None:
+        assert grid.Nx > 1 and grid.Nz > 1
+        xlabel, ylabel = "z", "x"
+        Nx, Ny = grid.Nz, grid.Nx
+        pbx, pby = _PeriodicBoundaryZ, _PeriodicBoundaryX
+        pmlxl, pmlxh, pmlyl, pmlyh = _PMLZlow, _PMLZhigh, _PMLXlow, _PMLXhigh
+        grid_energy = grid_energy[:, y, :].T
+    elif z is not None:
+        assert grid.Nx > 1 and grid.Ny > 1
+        xlabel, ylabel = "x", "y"
+        Nx, Ny = grid.Nx, grid.Ny
+        pbx, pby = _PeriodicBoundaryX, _PeriodicBoundaryY
+        pmlxl, pmlxh, pmlyl, pmlyh = _PMLXlow, _PMLXhigh, _PMLYlow, _PMLYhigh
+        grid_energy = grid_energy[:, :, z]
+    else:
+        raise ValueError("Visualization only works for 2D grids")
+
+    for source in grid.sources:
+        if isinstance(source, LineSource):
+            if x is not None:
+                _x = [source.y[0], source.y[-1]]
+                _y = [source.z[0], source.z[-1]]
+            elif y is not None:
+                _x = [source.z[0], source.z[-1]]
+                _y = [source.x[0], source.x[-1]]
+            elif z is not None:
+                _x = [source.x[0], source.x[-1]]
+                _y = [source.y[0], source.y[-1]]
+            plt.plot(_y, _x, lw=3, color=srccolor)
+        elif isinstance(source, PointSource):
+            if x is not None:
+                _x = source.y
+                _y = source.z
+            elif y is not None:
+                _x = source.z
+                _y = source.y
+            elif z is not None:
+                _x = source.x
+                _y = source.y
+            plt.plot(_y - 0.5, _x - 0.5, lw=3, marker="o", color=srccolor)
+            grid_energy[_x, _y] = 0  # do not visualize energy at location of source
+        elif isinstance(source, PlaneSource):
+            if x is not None:
+                _x = (
+                    source.y
+                    if source.y.stop > source.y.start + 1
+                    else slice(source.y.start, source.y.start)
+                )
+                _y = (
+                    source.z
+                    if source.z.stop > source.z.start + 1
+                    else slice(source.z.start, source.z.start)
+                )
+            elif y is not None:
+                _x = (
+                    source.z
+                    if source.z.stop > source.z.start + 1
+                    else slice(source.z.start, source.z.start)
+                )
+                _y = (
+                    source.x
+                    if source.x.stop > source.x.start + 1
+                    else slice(source.x.start, source.x.start)
+                )
+            elif z is not None:
+                _x = (
+                    source.x
+                    if source.x.stop > source.x.start + 1
+                    else slice(source.x.start, source.x.start)
+                )
+                _y = (
+                    source.y
+                    if source.y.stop > source.y.start + 1
+                    else slice(source.y.start, source.y.start)
+                )
+            patch = ptc.Rectangle(
+                xy=(_y.start - 0.5, _x.start - 0.5),
+                width=_y.stop - _y.start,
+                height=_x.stop - _x.start,
+                linewidth=0,
+                edgecolor="none",
+                facecolor=srccolor,
+            )
+            plt.gca().add_patch(patch)
+
+    # Detector
+    for detector in grid.detectors:
+        if x is not None:
+            _x = [detector.y[0], detector.y[-1]]
+            _y = [detector.z[0], detector.z[-1]]
+        elif y is not None:
+            _x = [detector.z[0], detector.z[-1]]
+            _y = [detector.x[0], detector.x[-1]]
+        elif z is not None:
+            _x = [detector.x[0], detector.x[-1]]
+            _y = [detector.y[0], detector.y[-1]]
+
+        if detector.__class__.__name__ == "BlockDetector":
+            # BlockDetector
+            plt.plot(
+                [_y[0], _y[1], _y[1], _y[0], _y[0]],
+                [_x[0], _x[0], _x[1], _x[1], _x[0]],
+                lw=3,
+                color=detcolor,
+            )
+        else:
+            # LineDetector
+            plt.plot(_y, _x, lw=3, color=detcolor)
+
+    # Boundaries
+    for boundary in grid.boundaries:
+        if isinstance(boundary, pbx):
+            _x = [-0.5, -0.5, float("nan"), Nx - 0.5, Nx - 0.5]
+            _y = [-0.5, Ny - 0.5, float("nan"), -0.5, Ny - 0.5]
+            plt.plot(_y, _x, color=pbcolor, linewidth=3)
+        elif isinstance(boundary, pby):
+            _x = [-0.5, Nx - 0.5, float("nan"), -0.5, Nx - 0.5]
+            _y = [-0.5, -0.5, float("nan"), Ny - 0.5, Ny - 0.5]
+            plt.plot(_y, _x, color=pbcolor, linewidth=3)
+        elif isinstance(boundary, pmlyl):
+            patch = ptc.Rectangle(
+                xy=(-0.5, -0.5),
+                width=boundary.thickness,
+                height=Nx,
+                linewidth=0,
+                edgecolor="none",
+                facecolor=pmlcolor,
+            )
+            plt.gca().add_patch(patch)
+        elif isinstance(boundary, pmlxl):
+            patch = ptc.Rectangle(
+                xy=(-0.5, -0.5),
+                width=Ny,
+                height=boundary.thickness,
+                linewidth=0,
+                edgecolor="none",
+                facecolor=pmlcolor,
+            )
+            plt.gca().add_patch(patch)
+        elif isinstance(boundary, pmlyh):
+            patch = ptc.Rectangle(
+                xy=(Ny - 0.5 - boundary.thickness, -0.5),
+                width=boundary.thickness,
+                height=Nx,
+                linewidth=0,
+                edgecolor="none",
+                facecolor=pmlcolor,
+            )
+            plt.gca().add_patch(patch)
+        elif isinstance(boundary, pmlxh):
+            patch = ptc.Rectangle(
+                xy=(-0.5, Nx - boundary.thickness - 0.5),
+                width=Ny,
+                height=boundary.thickness,
+                linewidth=0,
+                edgecolor="none",
+                facecolor=pmlcolor,
+            )
+            plt.gca().add_patch(patch)
+
+    for obj in grid.objects:
+        if x is not None:
+            _x = (obj.y.start, obj.y.stop)
+            _y = (obj.z.start, obj.z.stop)
+        elif y is not None:
+            _x = (obj.z.start, obj.z.stop)
+            _y = (obj.x.start, obj.x.stop)
+        elif z is not None:
+            _x = (obj.x.start, obj.x.stop)
+            _y = (obj.y.start, obj.y.stop)
+
+        patch = ptc.Rectangle(
+            xy=(min(_y) - 0.5, min(_x) - 0.5),
+            width=max(_y) - min(_y),
+            height=max(_x) - min(_x),
+            linewidth=0,
+            edgecolor="none",
+            facecolor=objcolor,
+        )
+        plt.gca().add_patch(patch)
+
+    # visualize the energy in the grid
+    cmap_norm = None
+    if norm == "log":
+        cmap_norm = LogNorm(vmin=1e-4, vmax=grid_energy.max() + 1e-4)
+    plt.imshow(bd.numpy(grid_energy), cmap=cmap, interpolation="sinc", norm=cmap_norm)
+
+    # finalize the plot
+    plt.ylabel(xlabel)
+    plt.xlabel(ylabel)
+    plt.ylim(Nx, -1)
+    plt.xlim(-1, Ny)
+    plt.figlegend()
+    plt.tight_layout()
+
+    # save frame (require folder path and index)
+    if save:
+        plt.savefig(os.path.join(folder, f"file{str(index).zfill(4)}.png"))
+
+    # show if not animating
+    if show:
+        plt.show()
+
+
+def dB_map_2D(block_det=None, choose_axis=2, interpolation="spline16"):
+    """
+    Displays detector readings from an 'fdtd.BlockDetector' in a decibel map spanning a 2D slice region inside the BlockDetector.
+    Compatible with continuous sources (not pulse).
+    Currently, only x-y 2D plot slices are accepted.
+
+    Parameter:-
+        block_det (numpy array): 5 axes numpy array (timestep, row, column, height, {x, y, z} parameter) created by 'fdtd.BlockDetector'.
+        (optional) choose_axis (int): Choose between {0, 1, 2} to display {x, y, z} data. Default 2 (-> z).
+        (optional) interpolation (string): Preferred 'matplotlib.pyplot.imshow' interpolation. Default "spline16".
+    """
+    if block_det is None:
+        raise ValueError(
+            "Function 'dBmap' requires a detector_readings object as parameter."
+        )
+    if len(block_det.shape) != 5:  # BlockDetector readings object have 5 axes
+        raise ValueError(
+            "Function 'dBmap' requires object of readings recorded by 'fdtd.BlockDetector'."
+        )
+
+    # TODO: convert all 2D slices (y-z, x-z plots) into x-y plot data structure
+
+    plt.ioff()
+    plt.close()
+    a = []  # array to store wave intensities
+    for i in tqdm(range(len(block_det[0]))):
+        a.append([])
+        for j in range(len(block_det[0][0])):
+            temp = [x[i][j][0][choose_axis] for x in block_det]
+            a[i].append(max(temp) - min(temp))
+
+    peakVal, minVal = max(map(max, a)), min(map(min, a))
+    print(
+        "Peak at:",
+        [
+            [[i, j] for j, y in enumerate(x) if y == peakVal]
+            for i, x in enumerate(a)
+            if peakVal in x
+        ],
+    )
+    a = 10 * log10([[y / minVal for y in x] for x in a])
+
+    plt.title("dB map of Electrical waves in detector region")
+    plt.imshow(a, cmap="inferno", interpolation=interpolation)
+    cbar = plt.colorbar()
+    cbar.ax.set_ylabel("dB scale", rotation=270)
+    plt.show()
+
+
+def plot_detection(detector_dict=None, specific_plot=None):
+    """
+    1. Plots intensity readings on array of 'fdtd.LineDetector' as a function of timestep.
+    2. Plots time of arrival of pulse at different LineDetector in array.
+    Compatible with pulse sources.
+
+    Args:
+        detector_dict (dictionary): Dictionary of detector readings, as created by 'fdtd.Grid.save_data()'.
+        (optional) specific_plot (string): Plot for a specific axis data. Choose from {"Ex", "Ey", "Ez", "Hx", "Hy", "Hz"}.
+    """
+    if detector_dict is None:
+        raise Exception(
+            "Function plotDetection() requires a dictionary of detector readings as 'detector_dict' parameter."
+        )
+    detectorElement = 0  # cell to consider in each detectors
+    maxArray = {}
+    plt.ioff()
+    plt.close()
+
+    for detector in detector_dict:
+        if len(detector_dict[detector].shape) != 3:
+            print("Detector '{}' not LineDetector; dumped.".format(detector))
+            continue
+        if specific_plot is not None:
+            if detector[-2] != specific_plot[0]:
+                continue
+        if detector[-2] == "E":
+            plt.figure(0, figsize=(15, 15))
+        elif detector[-2] == "H":
+            plt.figure(1, figsize=(15, 15))
+        for dimension in range(len(detector_dict[detector][0][0])):
+            if specific_plot is not None:
+                if ["x", "y", "z"].index(specific_plot[1]) != dimension:
+                    continue
+            # if specific_plot, subplot on 1x1, else subplot on 2x2
+            plt.subplot(
+                2 - int(specific_plot is not None),
+                2 - int(specific_plot is not None),
+                dimension + 1 if specific_plot is None else 1,
+            )
+            hilbertPlot = abs(
+                hilbert([x[0][dimension] for x in detector_dict[detector]])
+            )
+            plt.plot(hilbertPlot, label=detector)
+            plt.title(detector[-2] + "(" + ["x", "y", "z"][dimension] + ")")
+            if detector[-2] not in maxArray:
+                maxArray[detector[-2]] = {}
+            if str(dimension) not in maxArray[detector[-2]]:
+                maxArray[detector[-2]][str(dimension)] = []
+            maxArray[detector[-2]][str(dimension)].append(
+                [detector, where(hilbertPlot == max(hilbertPlot))[0][0]]
+            )
+
+    # Loop same as above, only to add axes labels
+    for i in range(2):
+        if specific_plot is not None:
+            if ["E", "H"][i] != specific_plot[0]:
+                continue
+        plt.figure(i)
+        for dimension in range(len(detector_dict[detector][0][0])):
+            if specific_plot is not None:
+                if ["x", "y", "z"].index(specific_plot[1]) != dimension:
+                    continue
+            plt.subplot(
+                2 - int(specific_plot is not None),
+                2 - int(specific_plot is not None),
+                dimension + 1 if specific_plot is None else 1,
+            )
+            plt.xlabel("Time steps")
+            plt.ylabel("Magnitude")
+        plt.suptitle("Intensity profile")
+    plt.legend()
+    plt.show()
+
+    for item in maxArray:
+        plt.figure(figsize=(15, 15))
+        for dimension in maxArray[item]:
+            arrival = bd.numpy(maxArray[item][dimension])
+            plt.plot(
+                [int(x) for x in arrival.T[1]],
+                arrival.T[0],
+                label=["x", "y", "z"][int(dimension)],
+            )
+        plt.title(item)
+        plt.xlabel("Time of arrival (time steps)")
+        plt.legend()
+        plt.suptitle("Time-of-arrival plot")
+    plt.show()
+
+
+#
+# def dump_to_vtk(pcb, filename, iteration, Ex_dump=False, Ey_dump=False, Ez_dump=False, Emag_dump=True, objects_dump=True, ports_dump=True):
+#     '''
+#     Extension is automatically chosen, you don't need to supply it
+#
+#     thanks
+#     https://pyscience.wordpress.com/2014/09/06/numpy-to-vtk-converting-your-numpy-arrays-to-vtk-arrays-and-files/
+#     https://bitbucket.org/pauloh/pyevtk/src/default/src/hl.py
+#
+#     Paraview needs a threshold operation to view the objects correctly.
+#
+#
+#     argument scaling_factor=None,True(epsilon and hbar), or Float, to accomodate reduced units
+#     or maybe
+#     '''
diff --git a/nidn/fdtd/waveforms.py b/nidn/fdtd/waveforms.py
new file mode 100644
index 0000000..52ba66e
--- /dev/null
+++ b/nidn/fdtd/waveforms.py
@@ -0,0 +1,53 @@
+# reverse literate programming?
+
+from math import sin, cos, sqrt, log, exp
+
+import numpy as np
+
+# For Hanning window pulses
+def hanning(f, t, n):
+    return (1 / 2) * (1 - cos(f * t / n)) * (sin(f * t))
+
+
+"""
+
+Recipes for Z measurements usually specify gaussian or gaussian derivative input pulses.
+
+Presumably because unlike a unit step or simply gated sine,
+they're smooth, introducing minimal numerical noise, while retaining broadband frequency components.
+
+I don't know what advantages the gaussian derivative provides over the gaussian.
+
+These gaussian pulses are normalized to have a peak value of 1.0.
+
+For derivation, see
+https://github.com/0xDBFB7/fdtd_PCB_extensions/blob/master/normalizedgaussian.nb.pdf
+
+http://www.cse.yorku.ca/~kosta/CompVis_Notes/fourier_transform_Gaussian.pdf
+http://www.sci.utah.edu/~gerig/CS7960-S2010/handouts/04%20Gaussian%20derivatives.pdf
+
+"""
+
+fwhm_constant = 2.0 * sqrt(2.0 * log(2))
+
+
+def normalized_gaussian_pulse(x, fwhm, center=0.0):
+    # '''
+    # x - input value, usually time
+    # fwhm - pulse Full Width Half Maximum
+    # Center - just for convenience, used to move pulse time around
+    # '''
+    # apparently FWHM of t is properly called "full duration half maximum",
+    # but I've never heard that used
+
+    # TODO: flag on input type and use backend?
+
+    sigma = fwhm / fwhm_constant
+    return np.exp(-(((x - center) ** 2.0) / (2.0 * (sigma**2.0))))
+
+
+def normalized_gaussian_derivative_pulse(x, fwhm, center=0.0):
+    sigma = fwhm / fwhm_constant
+    return (
+        exp((1.0 / 2.0) - ((x - center) ** 2.0) / (2.0 * sigma**2.0)) * (x - center)
+    ) / sigma
diff --git a/nidn/fdtd_integration/__init__.py b/nidn/fdtd_integration/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/nidn/fdtd/calculate_transmission_reflection_coefficients.py b/nidn/fdtd_integration/calculate_transmission_reflection_coefficients.py
similarity index 62%
rename from nidn/fdtd/calculate_transmission_reflection_coefficients.py
rename to nidn/fdtd_integration/calculate_transmission_reflection_coefficients.py
index 08bee47..f5205c6 100644
--- a/nidn/fdtd/calculate_transmission_reflection_coefficients.py
+++ b/nidn/fdtd_integration/calculate_transmission_reflection_coefficients.py
@@ -1,10 +1,10 @@
 from dotmap import DotMap
 from torch.fft import rfft, rfftfreq
-import numpy as np
-import torch
-import numpy
+from torch import sqrt, tensor
 
-from nidn.utils.global_constants import SPEED_OF_LIGHT
+from nidn.fdtd_integration.constants import FDTD_GRID_SCALE
+
+from ..utils.global_constants import SPEED_OF_LIGHT
 
 
 def calculate_transmission_reflection_coefficients(
@@ -24,26 +24,30 @@ def calculate_transmission_reflection_coefficients(
     Returns:
         tuple[float, float]: Transmission coefficient and reflection coefficient
     """
-    # If method == 'MEAN SQUARE, then use the mean square to get the coefficients
-    # If method == 'FT', use fourier transform method
+    # Substract the free_space reflection signal from the material reflection signal, to eliminate unreflected signal from detector
+    # The detector detects signal passing through both ways, and is placed between the source and the material.
+    # Thus, most of the signal present is the unreflected signal, which must be removed.
+    true_reflection = [
+        reflection_signals[1][i] - reflection_signals[0][i]
+        for i in range(len(reflection_signals[0]))
+    ]
 
     if time_to_frequency_domain_method.upper() == "MEAN SQUARE":
         transmission_coefficient = _mean_square(transmission_signals[1]) / _mean_square(
             transmission_signals[0]
         )
-        reflection_coefficient = _mean_square(reflection_signals[1]) / _mean_square(
+        reflection_coefficient = _mean_square(true_reflection) / _mean_square(
             reflection_signals[0]
         )
+
+    # TODO: Finish the FFT version. Not sure if this can be done with a single dirac pulse as signal, or repeated for every frequency. The formula is:
+    # t(w) = F(transmission signal with layers)/F(transmission signal free space)*exp(j*x_position*some coefficient)
     elif time_to_frequency_domain_method.upper() == "FOURIER TRANSFORM":
-        transmission_coefficient = (
-            _fft(transmission_signals[1], cfg)
-            / _fft(transmission_signals[0], cfg)
-            * np.exp()
-        )  # Some exponential should be multiplied here
-        reflection_coefficient = (
-            _fft(reflection_signals[1], cfg)
-            / _fft(reflection_signals[0], cfg)
-            * np.exp()
+        transmission_coefficient = _fft(transmission_signals[1], cfg) / _fft(
+            transmission_signals[0], cfg
+        )
+        reflection_coefficient = _fft(true_reflection, cfg) / _fft(
+            reflection_signals[0], cfg
         )
     return transmission_coefficient, reflection_coefficient
 
@@ -70,9 +74,9 @@ def _fft(signal, cfg: DotMap):
         tuple[array,array]: fourier frequenices and their corresponding values
     """
     sampling_frequencies = (
-        cfg.physical_wavelength_range[0] * 0.1 / (torch.sqrt(2) * SPEED_OF_LIGHT)
+        cfg.physical_wavelength_range[0] * FDTD_GRID_SCALE / (sqrt(2) * SPEED_OF_LIGHT)
     )
-    tensor_signal = torch.tensor(signal)
+    tensor_signal = tensor(signal)
 
     yf = rfft(tensor_signal)
     xf = rfftfreq(cfg.FDTD_niter, sampling_frequencies)
diff --git a/nidn/fdtd_integration/compute_spectrum_fdtd.py b/nidn/fdtd_integration/compute_spectrum_fdtd.py
new file mode 100644
index 0000000..91feec9
--- /dev/null
+++ b/nidn/fdtd_integration/compute_spectrum_fdtd.py
@@ -0,0 +1,145 @@
+from dotmap import DotMap
+from tqdm import tqdm
+from torch import sqrt, tensor
+from loguru import logger
+
+from ..trcwa.get_frequency_points import get_frequency_points
+from .calculate_transmission_reflection_coefficients import (
+    calculate_transmission_reflection_coefficients,
+)
+from .init_fdtd import init_fdtd
+
+
+def compute_spectrum_fdtd(permittivity, cfg: DotMap):
+    """Generates a spectrum of transmission and reflection coefficients for the specified wavelengths in the cfg, by using FDTD simulations.
+
+    Args:
+        permitivity (torch.tensor): Array of permittivity for each layer
+        cfg (DotMap): Configurations needed to perform the simulations
+
+    Returns:
+        tuple[array, array]: Transmission spectrum and reflection spectrum
+    """
+    transmission_spectrum = []
+    reflection_spectrum = []
+    physical_wavelengths, norm_freq = get_frequency_points(cfg)
+    logger.debug("Wavelenghts in spectrum")
+    logger.debug(physical_wavelengths)
+
+    # For each wavelength, calculate transmission and reflection coefficents
+    disable_progress_bar = logger._core.min_level >= 20
+    for i in tqdm(range(len(physical_wavelengths)), disable=disable_progress_bar):
+        transmission_signal = []
+        reflection_signal = []
+
+        # Create simulation in free space and run it
+        grid, transmission_detector, reflection_detector = init_fdtd(
+            cfg,
+            include_object=False,
+            wavelength=physical_wavelengths[i],
+            permittivity=permittivity[:, :, :, i],
+        )
+        grid.run(cfg.FDTD_niter, progress_bar=False)
+        transmission_free_space, reflection_free_space = _get_detector_values(
+            transmission_detector, reflection_detector
+        )
+        transmission_signal.append(transmission_free_space)
+        reflection_signal.append(reflection_free_space)
+
+        # Create the same simulation, but add material in the form of one or many layers, and run again
+        grid, transmission_detector, reflection_detector = init_fdtd(
+            cfg,
+            include_object=True,
+            wavelength=physical_wavelengths[i],
+            permittivity=permittivity[:, :, :, i],
+        )
+        grid.run(cfg.FDTD_niter, progress_bar=False)
+        transmission_material, reflection_material = _get_detector_values(
+            transmission_detector, reflection_detector
+        )
+        transmission_signal.append(transmission_material)
+        reflection_signal.append(reflection_material)
+        time = [i for i in range(len(transmission_signal[0]))]
+
+        # Calculate transmission and reflection coefficients,
+        # by using the signals from the free space simulation and the material simulation
+        (
+            transmission_coefficient,
+            reflection_coefficient,
+        ) = calculate_transmission_reflection_coefficients(
+            transmission_signal, reflection_signal, "MEAN SQUARE", cfg
+        )
+        transmission_spectrum.append(transmission_coefficient)
+        reflection_spectrum.append(reflection_coefficient)
+
+    logger.debug("Trasmission spectrum")
+    logger.debug(transmission_spectrum)
+    logger.debug("Reflection spectrum")
+    logger.debug(reflection_spectrum)
+
+    return transmission_spectrum, reflection_spectrum
+
+
+def _get_detector_values(transmission_detector, reflection_detector):
+    """Extract the signals detected by the transmission detector and the reflection detector
+
+    Args:
+        transmission_detector (fdtd.LineDetector): The transmission detector attached to the grid
+        reflection_detector (fdtd.LineDetector): The reflection detector attached to the grid
+        detector_position_y (int): The position along the linedetector which should be used
+
+    Returns:
+        tuple[array, array]: The electric field detected by the transmission detector, and the electric field detected by the reflection detector
+    """
+    e_transmission = _get_abs_value_from_3D_signal(
+        transmission_detector.detector_values()["E"]
+    )
+    e_reflection = _get_abs_value_from_3D_signal(
+        reflection_detector.detector_values()["E"]
+    )
+    h_transmission = _get_abs_value_from_3D_signal(
+        transmission_detector.detector_values()["H"]
+    )
+    h_reflection = _get_abs_value_from_3D_signal(
+        reflection_detector.detector_values()["H"]
+    )
+    return e_transmission, e_reflection
+
+
+def _get_abs_value_from_3D_signal(signal):
+    """Get the absolute value of a three-dimentional signal. For each time step, a =sqrt(x**2 + y**2 + z**2)
+
+    Args:
+        signal (array): Three dimentional time signal
+
+    Returns:
+        Array: One dimentional time-signal
+    """
+    signal = _average_along_detector(signal)
+
+    abs_value = []
+    for i in range(len(signal)):
+        abs_value.append(
+            sqrt(tensor(signal[i][0] ** 2 + signal[i][1] ** 2 + signal[i][2] ** 2))
+        )
+    return abs_value
+
+
+def _average_along_detector(signal):
+    """Average the signal along each point of a line detector
+
+    Args:
+        signal (Array[timesteps, points_on_detector,3]): E or H -field signal from a line detector
+
+    Returns:
+        Array[timesteps, 3]: averaged signal along detector
+    """
+    avg = []
+    for e in signal:
+        s = [tensor(0.0), tensor(0.0), tensor(0.0)]
+        for p in e:
+            s[0] += p[0] / len(e)
+            s[1] += p[1] / len(e)
+            s[2] += p[2] / len(e)
+        avg.append(s)
+    return avg
diff --git a/nidn/fdtd_integration/constants.py b/nidn/fdtd_integration/constants.py
new file mode 100644
index 0000000..2266494
--- /dev/null
+++ b/nidn/fdtd_integration/constants.py
@@ -0,0 +1,1 @@
+FDTD_GRID_SCALE = 0.1  # The ratio between the grid size and the smallest wavelength.
diff --git a/nidn/fdtd/init_fdtd.py b/nidn/fdtd_integration/init_fdtd.py
similarity index 67%
rename from nidn/fdtd/init_fdtd.py
rename to nidn/fdtd_integration/init_fdtd.py
index f2128e0..506c8d9 100644
--- a/nidn/fdtd/init_fdtd.py
+++ b/nidn/fdtd_integration/init_fdtd.py
@@ -1,8 +1,8 @@
 from dotmap import DotMap
 import fdtd
 
-from nidn.fdtd.constants import FDTD_UNIT_MAGNITUDE
-from nidn.utils.global_constants import SPEED_OF_LIGHT
+from ..utils.global_constants import EPS_0, SPEED_OF_LIGHT, UNIT_MAGNITUDE
+from .constants import FDTD_GRID_SCALE
 
 
 def init_fdtd(cfg: DotMap, include_object, wavelength, permittivity):
@@ -17,17 +17,15 @@ def init_fdtd(cfg: DotMap, include_object, wavelength, permittivity):
     Returns:
         fdtd:Grid: Grid with all the added object, ready to be run
     """
-    scaling = FDTD_UNIT_MAGNITUDE / (cfg.physical_wavelength_range[0] * 0.1)
+    fdtd.set_backend("torch")
+    scaling = UNIT_MAGNITUDE / (cfg.physical_wavelength_range[0] * FDTD_GRID_SCALE)
+    x_grid_size = int(
+        scaling * (cfg.FDTD_grid[0] + cfg.N_layers * cfg.PER_LAYER_THICKNESS[0])
+    )
+    y_grid_size = int(cfg.FDTD_grid[1] * scaling)
     grid = fdtd.Grid(
-        (
-            int(cfg.FDTD_grid[0] * scaling),
-            int(
-                cfg.FDTD_grid[1] * scaling
-                + cfg.N_layers * scaling * cfg.FDTD_per_layer_thickness
-            ),
-            int(cfg.FDTD_grid[2] * scaling),
-        ),
-        grid_spacing=cfg.physical_wavelength_range[0] * 0.1,
+        (x_grid_size, y_grid_size, 1),
+        grid_spacing=cfg.physical_wavelength_range[0] * FDTD_GRID_SCALE,
         permittivity=1.0,
         permeability=1.0,
     )
@@ -35,8 +33,11 @@ def init_fdtd(cfg: DotMap, include_object, wavelength, permittivity):
     grid, t_detector, r_detector = _add_detectors(
         grid,
         int(
-            cfg.FDTD_reflection_detector_x * scaling
-            + cfg.N_layers * scaling * cfg.FDTD_per_layer_thickness
+            scaling
+            * (
+                cfg.FDTD_reflection_detector_x
+                + cfg.N_layers * cfg.PER_LAYER_THICKNESS[0]
+            )
         ),
         int(cfg.FDTD_reflection_detector_x * scaling),
     )
@@ -53,14 +54,25 @@ def init_fdtd(cfg: DotMap, include_object, wavelength, permittivity):
             grid = _add_object(
                 grid,
                 int(
-                    cfg.FDTD_free_space_distance * scaling
-                    + i * scaling * cfg.FDTD_per_layer_thickness
+                    scaling
+                    * (
+                        cfg.FDTD_pml_thickness
+                        + cfg.FDTD_free_space_distance
+                        + i * cfg.PER_LAYER_THICKNESS[0]
+                    )
                 ),
                 int(
-                    cfg.FDTD_object[1] * scaling
-                    + (i + 1) * scaling * cfg.FDTD_per_layer_thickness
+                    scaling
+                    * (
+                        cfg.FDTD_pml_thickness
+                        + cfg.FDTD_free_space_distance
+                        + (i + 1) * cfg.PER_LAYER_THICKNESS[0]
+                    )
                 ),
-                permittivity[i],
+                permittivity[0][0][
+                    i
+                ],  # TODO: Implement possibility for patterned grid, currently uniform layer is used
+                frequency=SPEED_OF_LIGHT / wavelength,
             )
     return grid, t_detector, r_detector
 
@@ -75,10 +87,14 @@ def _add_boundaries(grid, pml_thickness):
     Returns:
         fdtd.Grid: The grid with the added boundaries
     """
-
+    # Add PML boundary to the left side of the grid
     grid[0:pml_thickness, :, :] = fdtd.PML(name="pml_xlow")
+    # Add PML boundary to the right side of the grid
     grid[-pml_thickness:, :, :] = fdtd.PML(name="pml_xhigh")
+    # Add periodic boundaries at both sides in y-direction
     grid[:, 0, :] = fdtd.PeriodicBoundary(name="ybounds")
+    # Add periodic boundaries on both sides in z-direction. Only applicable for 3D grids
+    # grid[:, :, 0] = fdtd.PeriodicBoundary(name="zbounds")
     return grid
 
 
@@ -130,7 +146,7 @@ def _add_detectors(grid, transmission_detector_x, reflection_detector_x):
     return grid, transmission_detector, reflection_detector
 
 
-def _add_object(grid, object_start_x, object_end_x, permittivity):
+def _add_object(grid, object_start_x, object_end_x, permittivity, frequency):
     """Add a object to the fdtd grid, with a specified permittivity. The object covers the entire grid in the y-direction.
 
     Args:
@@ -142,8 +158,10 @@ def _add_object(grid, object_start_x, object_end_x, permittivity):
     Returns:
         fdtd.Grid: The grid with the added object
     """
-
-    grid[object_start_x:object_end_x, :, :] = fdtd.AnisotropicObject(
-        permittivity=permittivity, name="object"
+    # Not sure whether the conductivity should be relative or absolute, i.e. if it should be multiplied with EPS_0.
+    # Since the permittivity is set to 1 for the free space grid, I'll leave it at an relative value for now. Also, permittivity for object is relative.
+    grid[object_start_x:object_end_x, :, :] = fdtd.AbsorbingObject(
+        permittivity=permittivity.real,
+        conductivity=permittivity.imag * frequency,
     )
     return grid
diff --git a/nidn/materials/find_closest_material.py b/nidn/materials/find_closest_material.py
index 858e760..92cbe98 100644
--- a/nidn/materials/find_closest_material.py
+++ b/nidn/materials/find_closest_material.py
@@ -6,11 +6,11 @@
 def _find_closest_material(eps, run_cfg):
     """Finds the closest matching material and distance to that (in epsilon)
     from a given epsilon grid.
-    
+
     Args:
         eps (torch.tensor): A tensor of epsilon values (Nx,Ny,N_layers,N_freq).
         run_cfg (DotMap): Run configuration.
-    
+
     Returns:
         tuple: The closest materials and distances to that.
     """
@@ -20,7 +20,13 @@ def _find_closest_material(eps, run_cfg):
     material_collection = MaterialCollection(run_cfg.target_frequencies)
 
     comparisons = torch.zeros(
-        [Nx, Ny, N_layers, N_freq, material_collection.N_materials,]
+        [
+            Nx,
+            Ny,
+            N_layers,
+            N_freq,
+            material_collection.N_materials,
+        ]
     )
 
     # Compute differences for all materials
diff --git a/nidn/materials/layer_builder.py b/nidn/materials/layer_builder.py
index c3d30bc..360c210 100644
--- a/nidn/materials/layer_builder.py
+++ b/nidn/materials/layer_builder.py
@@ -90,7 +90,7 @@ def build_circle_layer(
         eps[:, :] = self.material_collection[grid_material]
 
         # Define the circle
-        ind = (grid_x - x_center) ** 2 + (grid_y - y_center) ** 2 < radius ** 2
+        ind = (grid_x - x_center) ** 2 + (grid_y - y_center) ** 2 < radius**2
 
         eps[ind] = self.material_collection[circle_material]
 
diff --git a/nidn/notebooks/plot_fdtd_spectrum.ipynb b/nidn/notebooks/plot_fdtd_spectrum.ipynb
deleted file mode 100644
index 769fc18..0000000
--- a/nidn/notebooks/plot_fdtd_spectrum.ipynb
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "import sys\n",
-    "sys.path.append(\"../\")\n",
-    "from scripts.compute_fdtd_spectrum import plot_fdtd_spectrum\n",
-    "import nidn"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "cfg = nidn.load_default_cfg()\n",
-    "plot_fdtd_spectrum(cfg)"
-   ]
-  }
- ],
- "metadata": {
-  "interpreter": {
-   "hash": "cd0991b29d7d690bc5e205a01d9268c3e1c540c626acb4d966155a50f21eac25"
-  },
-  "kernelspec": {
-   "display_name": "Python 3.9.10 ('nidn')",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.9.10"
-  },
-  "orig_nbformat": 4
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/nidn/scripts/compute_fdtd_spectrum.py b/nidn/scripts/compute_fdtd_spectrum.py
deleted file mode 100644
index f3a8d01..0000000
--- a/nidn/scripts/compute_fdtd_spectrum.py
+++ /dev/null
@@ -1,226 +0,0 @@
-import fdtd
-from dotmap import DotMap
-import sys
-import torch
-
-sys.path.append("../")
-
-import nidn
-
-
-# This function computes the transmission and reflection spectrum of the material composition specified in the cfg file,
-# by using FDTD simulations. Example and documentations can be found here: https://fdtd.readthedocs.io/en/latest/examples.html
-def compute_fdtd_spectrum(cfg: DotMap):
-    transmission_spectrum = []
-    reflection_spectrum = []
-    fdtd.set_backend("torch")
-    grid_spacing = cfg.physical_wavelength_range[0] * 0.1
-    grid_size_x = 6e-6
-    grid_size_y = grid_spacing * 50  # optimal value to be investigated
-    transmission_detector_x = int(3.6 * 10 ** (-6) / (grid_spacing))
-    reflection_detector_x = int(2.4 * 10 ** (-6) / (grid_spacing))
-    source_x = int(1.6 * 10 ** (-6) / (grid_spacing))
-    source_y = grid_size_y / 2
-    pml_thickness = int(
-        1.5 * 10 ** (-6) / (grid_spacing)
-    )  # PML is a Perfectly Matched Layer, used as boundaries to absorb almost all radiation.
-    object_start_x = int(2.5 * 10 ** (-6) / (grid_spacing))
-    object_end_x = int(3.5 * 10 ** (-6) / (grid_spacing))
-    pulse_source = False
-    niter = 200
-    speed_of_light: float = 299_792_458.0  # [m/s] speed of light
-    use_point_source = True  # If false, line source is used
-    # Run two simulations for each frequency, one in free space and one with an object placed.
-    # Two detectors are placed in the grid, one just before the object and one just after.
-    # The transmission and reflectance coefficiioent respectively are calculating by dividing
-    # the rms value for the case with an object by the case wiithout the object
-
-    wavelengths, normalized_freq = nidn.get_frequency_points(cfg)
-    for wavelength in wavelengths:
-        # init grid
-        grid = fdtd.Grid(
-            (grid_size_x, grid_size_y, 1),
-            grid_spacing=grid_spacing,
-            permittivity=1.0,
-            permeability=1.0,
-        )
-        grid = _add_boundaries_to_grid(grid, pml_thickness)
-        # Source
-        grid = _add_source_to_grid(
-            grid,
-            use_point_source,
-            source_x,
-            source_y,
-            wavelength / speed_of_light,
-            pulse_source,
-        )
-
-        # Detectors
-        grid, transmission_detector, reflection_detector = _add_detectors_to_grid(
-            grid, transmission_detector_x, reflection_detector_x
-        )
-
-        # run simulation
-        grid.run(niter, progress_bar=False)
-        transmission_output = transmission_detector.detector_values()
-        reflection_output = reflection_detector.detector_values()
-        # Add object
-        grid2 = fdtd.Grid(
-            (grid_size_x, grid_size_y, 1),
-            grid_spacing=grid_spacing,
-            permittivity=1.0,
-            permeability=1.0,
-        )
-        grid2 = _add_boundaries_to_grid(grid2, pml_thickness)
-        grid2 = _add_source_to_grid(
-            grid2,
-            use_point_source,
-            source_x,
-            source_y,
-            wavelength / speed_of_light,
-            pulse_source,
-        )
-        grid2, transmission_detector2, reflection_detector2 = _add_detectors_to_grid(
-            grid2, transmission_detector_x, reflection_detector_x
-        )
-        grid2 = _add_object_to_grid(grid2, object_start_x, object_end_x)
-
-        # Run simulation again
-        grid2.run(niter, progress_bar=False)
-        transmission_output2 = transmission_detector2.detector_values()
-        reflection_output2 = reflection_detector2.detector_values()
-
-        transmission1_e_field_z_direction = [
-            e[int(source_x)][2] for e in transmission_output["E"]
-        ]
-        reflection_e_field_z_direction = [
-            e[int(source_x)][2] for e in reflection_output["E"]
-        ]
-        transmission1_e_field_z_direction2 = [
-            e[int(source_x)][2] for e in transmission_output2["E"]
-        ]
-        reflection_e_field_z_direction2 = [
-            e[int(source_x)][2] for e in reflection_output2["E"]
-        ]
-        # Substract the free space signal from the reflection detector in the case where the object is present
-        # to ensure oly the reflected signal is measured
-        compensated_reflection = [
-            reflection_e_field_z_direction2[i] - reflection_e_field_z_direction[i]
-            for i in range(len(reflection_e_field_z_direction2))
-        ]
-
-        # As the energy of a wave is proportional to E^2, and rms is theoretically equal E/2, only the mean squre is used
-        transmission_ms_1 = _calculate_mean_square(transmission1_e_field_z_direction)
-        transmission_ms_2 = _calculate_mean_square(transmission1_e_field_z_direction2)
-        reflection_ms_1 = _calculate_mean_square(reflection_e_field_z_direction)
-        reflection_ms_2 = _calculate_mean_square(compensated_reflection)
-
-        transmission_spectrum.append(transmission_ms_2 / transmission_ms_1)
-        reflection_spectrum.append(reflection_ms_2 / reflection_ms_1)
-        grid.reset()
-        grid2.reset()
-    return transmission_spectrum, reflection_spectrum
-
-
-# Calculate the spectrum from a cfg file, and plot this.
-# params:
-# cfg: the cfg file containing parameters to use in the simulation
-# returns : None
-def plot_fdtd_spectrum(cfg: DotMap):
-    transmission_spectrum, reflection_spectrum = compute_fdtd_spectrum(cfg)
-    nidn.plot_spectrum(cfg, reflection_spectrum, transmission_spectrum)
-
-
-# Helper function to add boundaries to a created grid.
-# It creates PML boundaries in the x-direction, and periodic boundaries in the y-direction
-# TODO: Implement further customability of boundary types, i.e. choose where pml or periodic boundaries should be
-#
-# params:
-# grid: the grid which to add the boundaries
-# pml_thickness: the thickness of the perfectly matched layer.
-
-# returns:
-# grid: the grid with the attached boundaries
-
-
-def _add_boundaries_to_grid(grid, pml_thickness):
-    grid[0:pml_thickness, :, :] = fdtd.PML(name="pml_xlow")
-    grid[-pml_thickness:, :, :] = fdtd.PML(name="pml_xhigh")
-    grid[:, 0, :] = fdtd.PeriodicBoundary(name="ybounds")
-
-    return grid
-
-
-# Helper function to add a source to a created grid.
-# Uses either a point source or a line source at the specified location
-#
-# params:
-# grid: the grid which to add the boundaries
-# use_point_source: bool - Point source if true, Line source if false
-# source_x, source_y: x and y location of the source, y position insignificant if line-source
-# period: period of the wave the source is emitting. Pass wavelength/speed_of_light
-# pulse_source: Whether the source should emitt a single pulse (True), or use a continuouss wave(False)
-
-# returns:
-# grid: the grid with the attached source
-
-
-def _add_source_to_grid(
-    grid, use_point_source, source_x, source_y, period, pulse_source
-):
-    if use_point_source:
-        grid[source_x, source_y, 0] = fdtd.PointSource(
-            period=period,
-            name="linesource",
-            pulse=pulse_source,
-            cycle=1,
-            hanning_dt=1e-15,
-        )
-    else:
-        grid[source_x, :, 0] = fdtd.LineSource(period=period, name="linesource")
-
-    return grid
-
-
-# Helper function to add detectors to the grid
-#
-# params:
-# grid: the grid which to add the boundaries
-# transmission_detector_x, reflection_detector_x: The x location of the transmission and reflection detector.
-
-# returns:
-# grid: the grid with the attached detectors
-# transmission_detector, reflection_detector: The two detectors for further use after the simulation is run
-def _add_detectors_to_grid(grid, transmission_detector_x, reflection_detector_x):
-
-    transmisssion_detector = fdtd.LineDetector(name="t_detector")
-    reflection_detector = fdtd.LineDetector(name="r_detector")
-    grid[transmission_detector_x, :, 0] = transmisssion_detector
-    grid[reflection_detector_x, :, 0] = reflection_detector
-
-    return grid, transmisssion_detector, reflection_detector
-
-
-# Helper function to add an object to the grid
-#
-# params:
-# grid: the grid which to add the object
-# object_start_x, object_end_x: The start and end position of the object
-
-# returns:
-# grid: the grid with the attached detectors
-def _add_object_to_grid(grid, object_start_x, object_end_x):
-    grid[object_start_x:object_end_x, :, :] = fdtd.AnisotropicObject(
-        permittivity=5.1984, name="object"
-    )
-    return grid
-
-
-# Helper function which calculates the mean square of an array
-# params:
-# arr: signal array on which t do the calculations on
-
-# returns:
-# The mean square value of the signal
-def _calculate_mean_square(arr):
-    return sum([e**2 for e in arr]) / len(arr)
diff --git a/nidn/training/model/model_to_eps_grid.py b/nidn/training/model/model_to_eps_grid.py
index 1a8dfb4..0ec0f72 100644
--- a/nidn/training/model/model_to_eps_grid.py
+++ b/nidn/training/model/model_to_eps_grid.py
@@ -129,7 +129,7 @@ def _regression_model_to_eps_grid(model, run_cfg: DotMap):
         run_cfg.N_layers,
         run_cfg.target_frequencies,
         run_cfg.freq_distribution,
-        run_cfg.TRCWA_PER_LAYER_THICKNESS,
+        run_cfg.PER_LAYER_THICKNESS,
     )
 
     # Reshape the output to have a 4D tensor again
@@ -211,7 +211,7 @@ def _classification_model_to_eps_grid(model, run_cfg: DotMap):
         run_cfg.N_layers,
         run_cfg.target_frequencies,
         run_cfg.freq_distribution,
-        run_cfg.TRCWA_PER_LAYER_THICKNESS,
+        run_cfg.PER_LAYER_THICKNESS,
     )
 
     # Reshape the output to have a 4D tensor again
diff --git a/nidn/training/run_training.py b/nidn/training/run_training.py
index 0c35eb2..df1477d 100644
--- a/nidn/training/run_training.py
+++ b/nidn/training/run_training.py
@@ -12,7 +12,7 @@
 from ..materials.material_collection import MaterialCollection
 from .model.init_network import init_network
 from .model.model_to_eps_grid import model_to_eps_grid
-from ..trcwa.compute_spectrum import compute_spectrum
+from ..utils.compute_spectrum import compute_spectrum
 from ..trcwa.compute_target_frequencies import compute_target_frequencies
 from ..utils.fix_random_seeds import fix_random_seeds
 from .utils.validate_config import _validate_config
diff --git a/nidn/training/utils/abs_layer.py b/nidn/training/utils/abs_layer.py
index 195a651..3b72a08 100644
--- a/nidn/training/utils/abs_layer.py
+++ b/nidn/training/utils/abs_layer.py
@@ -3,8 +3,7 @@
 
 
 class AbsLayer(nn.Module):
-    """Very simple activation layer to allow different abs layer activations of the siren.
-    """
+    """Very simple activation layer to allow different abs layer activations of the siren."""
 
     def __init__(self):
         super().__init__()
diff --git a/nidn/training/utils/validate_config.py b/nidn/training/utils/validate_config.py
index 8b74dfa..7684ae3 100644
--- a/nidn/training/utils/validate_config.py
+++ b/nidn/training/utils/validate_config.py
@@ -74,7 +74,7 @@ def _validate_config(cfg: DotMap):
     boolean_keys = ["use_regularization_loss", "add_noise", "use_gpu", "avoid_zero_eps"]
     string_keys = ["model_type", "type", "name", "freq_distribution"]
     list_keys = [
-        "TRCWA_PER_LAYER_THICKNESS",
+        "PER_LAYER_THICKNESS",
         "TRCWA_L_grid",
         "target_reflectance_spectrum",
         "target_transmittance_spectrum",
@@ -161,10 +161,10 @@ def _validate_config(cfg: DotMap):
         raise ValueError(f"thickness must a positive number.")
 
     if not (
-        len(cfg.TRCWA_PER_LAYER_THICKNESS) == cfg.N_layers
-        or len(cfg.TRCWA_PER_LAYER_THICKNESS) == 1
+        len(cfg.PER_LAYER_THICKNESS) == cfg.N_layers
+        or len(cfg.PER_LAYER_THICKNESS) == 1
     ):
-        raise ValueError(f"TRCWA_PER_LAYER_THICKNESS must have length 1 or N_layers")
+        raise ValueError(f"PER_LAYER_THICKNESS must have length 1 or N_layers")
 
     if not (cfg.freq_distribution == "linear" or cfg.freq_distribution == "log"):
         raise ValueError(f"freq_distribution must be either 'linear' or 'log'")
diff --git a/nidn/trcwa/compute_spectrum.py b/nidn/trcwa/compute_spectrum_trcwa.py
similarity index 97%
rename from nidn/trcwa/compute_spectrum.py
rename to nidn/trcwa/compute_spectrum_trcwa.py
index 00d1b2e..7d8ed1b 100644
--- a/nidn/trcwa/compute_spectrum.py
+++ b/nidn/trcwa/compute_spectrum_trcwa.py
@@ -5,7 +5,7 @@
 from .init_trcwa import _init_trcwa
 
 
-def compute_spectrum(eps_grid, run_cfg: DotMap):
+def compute_spectrum_trcwa(eps_grid, run_cfg: DotMap):
     """Evaluates TRCWA for the given epsilon values and run configuration.
 
     Args:
diff --git a/nidn/trcwa/constants.py b/nidn/trcwa/constants.py
index f6a4fbe..24e7822 100644
--- a/nidn/trcwa/constants.py
+++ b/nidn/trcwa/constants.py
@@ -1,10 +1,5 @@
 import torch
 
-# NB: Here, we assume that the standard is micrometre (um).
-TRCWA_UNIT_MAGNITUDE = 10 ** (-6)
-
-# m /s
-TRCWA_SPEED_OF_LIGHT = 299792458.0
 
 # Q_ABS is a parameter for relaxation to better approach global optimal, at Q_ABS= inf, it will describe the real physics.
 # It can also be used to resolve singular matrix issues by setting a large but finite Q_ABS, e.g. Q_ABS= 1e5.
@@ -21,13 +16,3 @@
 # Angles
 TRCWA_THETA = 0.0
 TRCWA_PHI = 0.0
-
-# elementary charge, C
-TRCWA_E_CHARGE = 1.602176634 * 10 ** (-19)
-# weight of electron, kg
-TRCWA_M_E = 9.1093837015 * 10 ** (-31)
-# vacuum permittivity, F/m
-TRCWA_EPS_0 = 8.8541878128 * 10 ** (-12)
-
-# There is no torch.pi so we define it here
-TRCWA_PI = torch.tensor(3.14159265358979323846264338327950288)
diff --git a/nidn/trcwa/init_trcwa.py b/nidn/trcwa/init_trcwa.py
index 4481d47..490b4a6 100644
--- a/nidn/trcwa/init_trcwa.py
+++ b/nidn/trcwa/init_trcwa.py
@@ -1,6 +1,7 @@
 from loguru import logger
 
 from .constants import *
+from ..utils.global_constants import *
 from .trcwa import TRCWA
 from ..materials.material_collection import MaterialCollection
 
@@ -50,10 +51,10 @@ def _init_trcwa(eps_grid, target_frequency, run_cfg):
     for layer in range(N_layers):
 
         # Set thickness based on config
-        if len(run_cfg.TRCWA_PER_LAYER_THICKNESS) == 1:
-            thickness = run_cfg.TRCWA_PER_LAYER_THICKNESS[0]
+        if len(run_cfg.PER_LAYER_THICKNESS) == 1:
+            thickness = run_cfg.PER_LAYER_THICKNESS[0]
         else:
-            thickness = run_cfg.TRCWA_PER_LAYER_THICKNESS[layer]
+            thickness = run_cfg.PER_LAYER_THICKNESS[layer]
 
         if Nx > 1 or Ny > 1:
             trcwa.Add_LayerGrid(thickness, Nx, Ny)
diff --git a/nidn/trcwa/trcwa.py b/nidn/trcwa/trcwa.py
index 7f734f7..3b25b61 100644
--- a/nidn/trcwa/trcwa.py
+++ b/nidn/trcwa/trcwa.py
@@ -1,5 +1,7 @@
 import torch
 
+from nidn.utils.global_constants import PI
+
 from .constants import *
 
 from .utils.fft_funs import Epsilon_fft, get_ifft
@@ -27,7 +29,7 @@ def __init__(self, nG, L1, L2, freq, theta, phi, verbose=1):
             verbose (int, optional): If verbose > 0, the actual nG is printed. Defaults to 1.
         """
         self.freq = freq
-        self.omega = 2 * TRCWA_PI * freq + 0.0j
+        self.omega = 2 * PI * freq + 0.0j
         self.L1 = L1
         self.L2 = L2
         self.phi = torch.tensor(phi)
@@ -675,12 +677,12 @@ def MakeKPMatrix(omega, layer_type, epinv, kx, ky):
         Jk = torch.vstack((torch.diag(-ky), torch.diag(kx)))
         JkkJT = torch_dot(Jk, torch_transpose(Jk))
 
-        kp = omega ** 2 * torch_eye(2 * nG) - epinv * JkkJT
+        kp = omega**2 * torch_eye(2 * nG) - epinv * JkkJT
     # patterned layer
     else:
         Jk = torch.vstack((torch.diag(-ky), torch.diag(kx)))
         tmp = torch_dot(Jk, epinv)
-        kp = omega ** 2 * torch_eye(2 * nG) - torch_dot(tmp, torch_transpose(Jk))
+        kp = omega**2 * torch_eye(2 * nG) - torch_dot(tmp, torch_transpose(Jk))
 
     return kp
 
@@ -698,7 +700,7 @@ def SolveLayerEigensystem_uniform(omega, kx, ky, epsilon):
         torch.tensor, torch.tensor: q, phi
     """
     nG = len(kx)
-    q = torch.sqrt(epsilon * omega ** 2 - kx ** 2 - ky ** 2)
+    q = torch.sqrt(epsilon * omega**2 - kx**2 - ky**2)
     # branch cut choice
     q = torch.where(torch.imag(q) < 0.0, -q, q)
 
diff --git a/nidn/trcwa/utils/kbloch.py b/nidn/trcwa/utils/kbloch.py
index 4a4bc6e..fc7f0dd 100644
--- a/nidn/trcwa/utils/kbloch.py
+++ b/nidn/trcwa/utils/kbloch.py
@@ -2,6 +2,7 @@
 import torch
 
 from ..constants import *
+from ...utils.global_constants import PI
 
 
 def Lattice_Reciprocate(L1, L2):
@@ -48,8 +49,8 @@ def Lattice_SetKs(G, kx0, ky0, Lk1, Lk2):
     2pi factor is now included in the returned kx,ky
     """
 
-    kx = kx0 + 2 * TRCWA_PI * (Lk1[0] * G[:, 0] + Lk2[0] * G[:, 1])
-    ky = ky0 + 2 * TRCWA_PI * (Lk1[1] * G[:, 0] + Lk2[1] * G[:, 1])
+    kx = kx0 + 2 * PI * (Lk1[0] * G[:, 0] + Lk2[0] * G[:, 1])
+    ky = ky0 + 2 * PI * (Lk1[1] * G[:, 0] + Lk2[1] * G[:, 1])
 
     return kx, ky
 
@@ -72,7 +73,7 @@ def Gsel_parallelogramic(nG, Lk1, Lk2):
     G2 = G2.flatten()
 
     # sorting
-    Gl2 = G1 ** 2 * u ** 2 + G2 ** 2 * v ** 2 + 2 * G2 * G1 * uv
+    Gl2 = G1**2 * u**2 + G2**2 * v**2 + 2 * G2 * G1 * uv
     sort = torch.argsort(Gl2)
     G1 = G1[sort]
     G2 = G2[sort]
@@ -99,10 +100,10 @@ def Gsel_circular(nG, Lk1, Lk2):
     uv = torch.dot(Lk1, Lk2)
     uxv = Lk1[0] * Lk2[1] - Lk1[1] * Lk2[0]
     circ_area = nG * torch.abs(uxv)
-    circ_radius = torch.sqrt(circ_area / TRCWA_PI) + u + v
+    circ_radius = torch.sqrt(circ_area / PI) + u + v
 
-    u_extent = 1 + int(circ_radius / (u * torch.sqrt(1.0 - uv ** 2 / (u * v) ** 2)))
-    v_extent = 1 + int(circ_radius / (v * torch.sqrt(1.0 - uv ** 2 / (u * v) ** 2)))
+    u_extent = 1 + int(circ_radius / (u * torch.sqrt(1.0 - uv**2 / (u * v) ** 2)))
+    v_extent = 1 + int(circ_radius / (v * torch.sqrt(1.0 - uv**2 / (u * v) ** 2)))
 
     uext21 = 2 * u_extent + 1
     vext21 = 2 * v_extent + 1
@@ -114,7 +115,7 @@ def Gsel_circular(nG, Lk1, Lk2):
     G2 = G2.flatten()
 
     # sorting
-    Gl2 = G1 ** 2 * u ** 2 + G2 ** 2 * v ** 2 + 2 * G2 * G1 * uv
+    Gl2 = G1**2 * u**2 + G2**2 * v**2 + 2 * G2 * G1 * uv
 
     # Torch's sorting algorithm is not stable, so we sort with numpy for reproducibility
     sort = np.argsort(Gl2.cpu().numpy())
@@ -130,7 +131,7 @@ def Gsel_circular(nG, Lk1, Lk2):
         nGtmp = nG
 
     # removing the part outside the cycle
-    tol = 1e-10 * max(u ** 2, v ** 2)
+    tol = 1e-10 * max(u**2, v**2)
     for i in range(nGtmp - 1, -1, -1):
         if torch.abs(Gl2[i] - Gl2[i - 1]) > tol:
             break
diff --git a/nidn/utils/compute_spectrum.py b/nidn/utils/compute_spectrum.py
new file mode 100644
index 0000000..b92a4c8
--- /dev/null
+++ b/nidn/utils/compute_spectrum.py
@@ -0,0 +1,18 @@
+from ..fdtd_integration.compute_spectrum_fdtd import compute_spectrum_fdtd
+from ..trcwa.compute_spectrum_trcwa import compute_spectrum_trcwa
+
+
+def compute_spectrum(eps_grid, cfg):
+    """Computes spectrum, using either TRCWA or FDTD simulations
+
+    Args:
+        cfg (DotMap): Configurations for the simulation
+        permittivity (Array[Nx][Ny][Nlayers][Nfrequencies]): Matrix of permittivity tensors
+
+    Returns:
+        Array, Array: Reflection spectrumand transmission spectrum
+    """
+    if cfg.solver == "FDTD":
+        return compute_spectrum_fdtd(eps_grid, cfg)
+    elif cfg.solver == "TRCWA":
+        return compute_spectrum_trcwa(eps_grid, cfg)
diff --git a/nidn/utils/convert_units.py b/nidn/utils/convert_units.py
index 502d71d..a2d21b3 100644
--- a/nidn/utils/convert_units.py
+++ b/nidn/utils/convert_units.py
@@ -1,4 +1,4 @@
-from nidn.trcwa.constants import TRCWA_UNIT_MAGNITUDE, TRCWA_SPEED_OF_LIGHT
+from .global_constants import UNIT_MAGNITUDE, SPEED_OF_LIGHT
 
 
 def freq_to_wl(freq):
@@ -23,7 +23,7 @@ def phys_wl_to_wl(phys_wl):
     Returns:
         float: The wavelength in units of TRCWA_UNIT_MAGNITUDE.
     """
-    return phys_wl / TRCWA_UNIT_MAGNITUDE
+    return phys_wl / UNIT_MAGNITUDE
 
 
 def wl_to_phys_wl(wl):
@@ -35,7 +35,7 @@ def wl_to_phys_wl(wl):
     Returns:
         float: The physical wavelength in metres.
     """
-    return wl * TRCWA_UNIT_MAGNITUDE
+    return wl * UNIT_MAGNITUDE
 
 
 def phys_freq_to_phys_wl(freq):
@@ -47,5 +47,5 @@ def phys_freq_to_phys_wl(freq):
     Returns:
         float: The physical frequency or the physical wavelength.
     """
-    c = TRCWA_SPEED_OF_LIGHT
+    c = SPEED_OF_LIGHT
     return c / freq
diff --git a/nidn/utils/global_constants.py b/nidn/utils/global_constants.py
index 29a4c2b..45b9e1a 100644
--- a/nidn/utils/global_constants.py
+++ b/nidn/utils/global_constants.py
@@ -1,7 +1,18 @@
 import torch
 
+# Elemental charge
 E_CHARGE = 1.602176634 * 10 ** (-19)
+# Mass of electron
 M_E = 9.1093837015 * 10 ** (-31)
-EPS_0 = 8.8541878128 * 10 ** (-12)
+# Vacuum permittivity
+EPS_0 = torch.tensor(8.8541878128 * 10 ** (-12))
+# There is no torch.pi so we define it here
 PI = torch.tensor(3.14159265358979323846264338327950288)
+# Speed of light in vacuum
 SPEED_OF_LIGHT = 299792458.0
+# Unit size in simulations
+UNIT_MAGNITUDE = 10 ** (-6)
+# Vacuum permeability
+MU_0: float = 4e-7 * PI
+# Vacuum impedance
+ETA_0: float = MU_0 * SPEED_OF_LIGHT
diff --git a/nidn/utils/resources/default_config.toml b/nidn/utils/resources/default_config.toml
index 53c2205..e38e0d0 100644
--- a/nidn/utils/resources/default_config.toml
+++ b/nidn/utils/resources/default_config.toml
@@ -28,27 +28,29 @@ real_max_eps = 100.0
 imag_min_eps = 0.0
 imag_max_eps = 3.0
 
+# Simulation type
+solver = "FDTD" # Options: FDTD, TRCWA
+
 # Grid dimensions
 Nx = 1
 Ny = 1
 N_layers = 8
+PER_LAYER_THICKNESS = [1.0] # len 1 for uniform thickness
+# PER_LAYER_THICKNESS = [0.1,0.5,0.4] # optionally list of thicknesses for each layer
 
 # TRCWA parameters
-TRCWA_PER_LAYER_THICKNESS = [1.0] # len 1 for uniform thickness
-# TRCWA_PER_LAYER_THICKNESS = [0.1,0.5,0.4] # optionally list of thicknesses for each layer
 TRCWA_L_grid = [[0.1,0.0],[0.0,0.1]] # grid dimension for TRCWA
 TRCWA_NG = 11 # Truncation order (actual number might be smaller)
 
 # FDTD parameters
-FDTD_grid = [5,2,1]
-FDTD_use_pointsource = false
-FDTD_use_pulsesource = false
-FDTD_pml_thickness = 1.5
-FDTD_source = [1.5,1.0]
-FDTD_free_space_distance = 1
-FDTD_reflection_detector_x = 2.4
-FDTD_niter = 200
-FDTD_PER_LAYER_THICKNESS = [1.0]
+FDTD_grid = [5.0,2.0,1.0] # Dimensions of the grid used in FDTD simulations, in FDTD unit magnitudes
+FDTD_use_pointsource = false # If the source should be a point source in the FDTD simulaitons, otherwise set as linesource 
+FDTD_use_pulsesource = false # If the source should be a single pulse in the FDTD simulations, otherwise set as continuous wave
+FDTD_pml_thickness = 1.5 # Thickness of PML layerin FDTD simulations, set in FDTD unit magnitudes. Perfectly Matched Layer are boundaries used in the x-direction, design to absrb all radiation
+FDTD_source = [1.5,1.0] # Coordinates of the source used in FDTD simulations, in FDTD unit magnitudes
+FDTD_free_space_distance = 1 # The thickness of the free space layer before and after the material layers, in FDTD unit magnitudes
+FDTD_reflection_detector_x = 2.4 # X-coordinates of the reflection detector for the FDTD simulation, in FDTD unit magnitudes
+FDTD_niter = 200 # Number of iterations / timesteps to run the FDTD for
 
 
 # Target spectra
@@ -60,3 +62,4 @@ target_transmittance_spectrum = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
 physical_wavelength_range = [1e-6,30e-6]
 freq_distribution = "linear" # "linear" or "log"
 N_freq = 20
+
diff --git a/notebooks/fdft_example.ipynb b/notebooks/fdft_example.ipynb
deleted file mode 100644
index c0c5548..0000000
--- a/notebooks/fdft_example.ipynb
+++ /dev/null
@@ -1,360 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "import matplotlib.pyplot as plt\n",
-    "import sys\n",
-    "sys.path.append(r\"C:\\Users\\to-bo\\OneDrive\\Documents\\ESA\\NIDN\\Developer\\nidn\")\n",
-    "\n",
-    "import nidn\n",
-    "import fdtd\n",
-    "import fdtd.backend as bd\n",
-    "from nidn.trcwa.init_trcwa import _init_trcwa"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "fdtd.set_backend(\"torch\")"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "cfg = nidn.load_default_cfg()\n",
-    "\n",
-    "WAVELENGTH = 5.35e-06\n",
-    "\n",
-    "GRID_SPACING = cfg.physical_wavelength_range[0]*0.1\n",
-    "GRID_SIZE_X = 6e-6\n",
-    "GRID_SIZE_Y = GRID_SPACING * 50 # optimal value to be investigated \n",
-    "TRANSMISSION_DETECTOR_X = int(3.6*10**(-6)/(GRID_SPACING))\n",
-    "REFLECTION_DETECTOR_X = int(2.4*10**(-6)/(GRID_SPACING))\n",
-    "SOURCE_X = int(1.6*10**(-6)/(GRID_SPACING))\n",
-    "SOURCE_Y = GRID_SIZE_Y/2\n",
-    "PML_THICKNESS = int(1.5*10**(-6)/(GRID_SPACING))\n",
-    "OBJECT_START_X = int(2.5*10**(-6)/(GRID_SPACING))\n",
-    "OBJECT_END_X = int(3.5*10**(-6)/(GRID_SPACING))\n",
-    "PULSE_SOURCE = False\n",
-    "SPEED_LIGHT: float = 299_792_458.0  # [m/s] speed of light"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "grid = fdtd.Grid(\n",
-    "    (GRID_SIZE_X, GRID_SIZE_Y, 1),\n",
-    "    grid_spacing=GRID_SPACING,\n",
-    "    permittivity=1.0,\n",
-    "    permeability=1.0\n",
-    ")\n",
-    "\n",
-    "# grid[0, :, :] = fdtd.PeriodicBoundary(name=\"xbounds\")\n",
-    "grid[0:PML_THICKNESS, :, :] = fdtd.PML(name=\"pml_xlow\")\n",
-    "grid[-PML_THICKNESS:, :, :] = fdtd.PML(name=\"pml_xhigh\")\n",
-    "\n",
-    "grid[:, 0, :] = fdtd.PeriodicBoundary(name=\"ybounds\")\n",
-    "#grid[:, 0:10, :] = fdtd.PML(name=\"pml_ylow\")\n",
-    "#grid[:, -10:, :] = fdtd.PML(name=\"pml_yhigh\")\n",
-    "\n",
-    "point = True\n",
-    "\n",
-    "if(point):\n",
-    "    grid[SOURCE_X,SOURCE_Y, 0] = fdtd.PointSource(\n",
-    "    period=WAVELENGTH / SPEED_LIGHT, name=\"linesource\",\n",
-    "    pulse =PULSE_SOURCE,\n",
-    "    cycle=1,\n",
-    "    hanning_dt=1e-15)\n",
-    "else:\n",
-    "        grid[SOURCE_X,:, 0] = fdtd.LineSource(\n",
-    "    period=WAVELENGTH / SPEED_LIGHT, name=\"linesource\")\n",
-    "\n",
-    "\n",
-    "\n",
-    "transmisssion_detector = fdtd.LineDetector(name=\"t_detector\")\n",
-    "reflection_detector = fdtd.LineDetector(name=\"r_detector\")\n",
-    "grid[TRANSMISSION_DETECTOR_X, :, 0] =transmisssion_detector\n",
-    "grid[REFLECTION_DETECTOR_X,:,0] = reflection_detector\n",
-    "\n",
-    "#grid[20:30,:, 0:1] = fdtd.AnisotropicObject(permittivity=2.5, name=\"object\")\n",
-    "\n",
-    "grid.run(300, progress_bar=False)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "plt.figure()\n",
-    "grid.visualize(z=0, animate = True)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "transmission_output = transmisssion_detector.detector_values()\n",
-    "reflection_output = reflection_detector.detector_values()\n",
-    "z_vals_t = [e[int(SOURCE_Y)][2] for e in transmission_output['E']]\n",
-    "z_vals_r = [e[int(SOURCE_Y)][2] for e in reflection_output['E']]\n",
-    "t = [i for i in range(len(z_vals_t))]\n",
-    "plt.plot(t,z_vals_t)\n",
-    "plt.plot(t,z_vals_r)\n",
-    "plt.show()\n",
-    "\n",
-    "intensity1 = 0\n",
-    "for i in z_vals_t:\n",
-    "    intensity1 += i**2\n",
-    "intensity1 = intensity1/len(z_vals_t)\n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "grid2 = fdtd.Grid(\n",
-    "    (GRID_SIZE_X, GRID_SIZE_Y, 1),\n",
-    "    grid_spacing=GRID_SPACING,\n",
-    "    permittivity=1.0,\n",
-    "    permeability=1.0\n",
-    ")\n",
-    "\n",
-    "# grid[0, :, :] = fdtd.PeriodicBoundary(name=\"xbounds\")\n",
-    "grid2[0:PML_THICKNESS, :, :] = fdtd.PML(name=\"pml_xlow\")\n",
-    "grid2[-PML_THICKNESS:, :, :] = fdtd.PML(name=\"pml_xhigh\")\n",
-    "\n",
-    "grid2[:, 0, :] = fdtd.PeriodicBoundary(name=\"ybounds\")\n",
-    "#grid2[:, 0:10, :] = fdtd.PML(name=\"pml_ylow\")\n",
-    "#grid2[:, -10:, :] = fdtd.PML(name=\"pml_yhigh\")\n",
-    "\n",
-    "point = True\n",
-    "\n",
-    "if(point):\n",
-    "    grid2[SOURCE_X,SOURCE_Y, 0] = fdtd.PointSource(\n",
-    "    period=WAVELENGTH / SPEED_LIGHT, name=\"linesource\",\n",
-    "    pulse = PULSE_SOURCE,\n",
-    "    cycle=1,\n",
-    "    hanning_dt=1e-15)\n",
-    "else:\n",
-    "    grid2[SOURCE_X,:, 0] = fdtd.LineSource(\n",
-    "    period=WAVELENGTH / SPEED_LIGHT, name=\"linesource\")\n",
-    "\n",
-    "\n",
-    "\n",
-    "transmisssion_detector2 = fdtd.LineDetector(name=\"t_detector\")\n",
-    "reflection_detector2 = fdtd.LineDetector(name=\"r_detector\")\n",
-    "grid2[TRANSMISSION_DETECTOR_X, :, 0] =transmisssion_detector2\n",
-    "grid2[REFLECTION_DETECTOR_X,:,0] = reflection_detector2\n",
-    "\n",
-    "grid2[OBJECT_START_X:OBJECT_END_X,:, :] = fdtd.AnisotropicObject(permittivity=5.1984, name=\"object\")\n",
-    "\n",
-    "grid2.run(300, progress_bar=False)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "plt.figure()\n",
-    "grid2.visualize(z=0, animate = True)\n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "transmission_output2 = transmisssion_detector2.detector_values()\n",
-    "reflection_output2 = reflection_detector2.detector_values()\n",
-    "z_vals_t2 = [e[int(SOURCE_Y)][2] for e in transmission_output2['E']]\n",
-    "z_vals_r2 = [e[int(SOURCE_Y)][2] for e in reflection_output2['E']]\n",
-    "t = [i for i in range(len(z_vals_t2))]\n",
-    "plt.plot(t,z_vals_t2)\n",
-    "#plt.plot(t,z_vals_r2)\n",
-    "plt.show()\n",
-    "hx_trans2 = [e[int(SOURCE_Y)][0] for e in transmission_output2['H']]\n",
-    "hy_trans2 = [e[int(SOURCE_Y)][1] for e in transmission_output2['H']]\n",
-    "\n",
-    "plt.plot(t,z_vals_t2)\n",
-    "plt.plot(t,z_vals_t)\n",
-    "plt.legend([\"Transmitted signal whith object\",\"Transmitted signal free space\"])\n",
-    "plt.show()\n",
-    "intensity2 = 0.00\n",
-    "for i in z_vals_t2:\n",
-    "    intensity2 += i**2\n",
-    "intensity2 = intensity2/len(z_vals_t2)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "intensity2 = 0.00\n",
-    "for i in z_vals_t2:\n",
-    "    intensity2 += i**2\n",
-    "intensity2 = intensity2/len(z_vals_t2)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "transmission = intensity2/intensity1\n",
-    "transmission"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "plt.plot(t,z_vals_t)\n",
-    "plt.plot(t,z_vals_t2)\n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "import numpy"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Correct phase shift"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "signal1 = z_vals_t\n",
-    "signal2 = z_vals_t2\n",
-    "max_phase_offset = 180\n",
-    "max_corr = 0\n",
-    "best_offset = 0\n",
-    "for offset in range(max_phase_offset):\n",
-    "    offset_sig = signal1[offset:] + signal1[:offset] # phase shift signal with concat  \n",
-    "    correlation = sum(sum(numpy.corrcoef(offset_sig,signal2)))\n",
-    "    if correlation > max_corr:\n",
-    "      max_corr = correlation \n",
-    "      best_offset = offset \n",
-    "#phasedshifted_sig = signal1[best_offset :] + signal1[:best_offset ] # phase shift signal with concat\n",
-    "phasedshifted_sig = [0  for i in range(200-best_offset)] + signal1[:best_offset ]"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "plt.plot(t,phasedshifted_sig)\n",
-    "plt.plot(t,signal2)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "intensity1 = 0\n",
-    "for i in signal2:\n",
-    "    intensity1 += i**2\n",
-    "intensity1 = intensity1/len(phasedshifted_sig)\n",
-    "intensity2 = 0\n",
-    "for i in phasedshifted_sig:\n",
-    "    intensity2 += i**2\n",
-    "intensity2 = intensity2/len(signal2)\n",
-    "\n",
-    "transmission = intensity1/intensity2\n",
-    "transmission"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "from scipy.fft import rfft, rfftfreq"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "signal1 = phasedshifted_sig\n",
-    "sample_rate = int((numpy.sqrt(2)*SPEED_LIGHT)/GRID_SPACING)\n",
-    "\n",
-    "yf1 = rfft(signal1)\n",
-    "yf2 = rfft(signal2)\n",
-    "xf = rfftfreq(200, sample_rate)\n",
-    "plt.plot(xf, numpy.abs(yf1))\n",
-    "plt.plot(xf, numpy.abs(yf2))\n",
-    "plt.show()"
-   ]
-  }
- ],
- "metadata": {
-  "interpreter": {
-   "hash": "cd0991b29d7d690bc5e205a01d9268c3e1c540c626acb4d966155a50f21eac25"
-  },
-  "kernelspec": {
-   "display_name": "Python 3.9.10 64-bit ('nidn': conda)",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.9.10"
-  },
-  "orig_nbformat": 4
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/notebooks/fdtd_example.ipynb b/notebooks/fdtd_example.ipynb
new file mode 100644
index 0000000..453affd
--- /dev/null
+++ b/notebooks/fdtd_example.ipynb
@@ -0,0 +1,541 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[32m16:22:36\u001b[0m|NIDN-\u001b[34mINFO\u001b[0m| \u001b[1mInitialized NIDN for cpu\u001b[0m\n",
+      "\u001b[32m16:22:36\u001b[0m|NIDN-\u001b[34mINFO\u001b[0m| \u001b[1mUsing double precision\u001b[0m\n"
+     ]
+    }
+   ],
+   "source": [
+    "import matplotlib.pyplot as plt\n",
+    "import sys\n",
+    "sys.path.append(r\"C:\\Users\\to-bo\\OneDrive\\Documents\\ESA\\NIDN\\Developer\\nidn\")\n",
+    "\n",
+    "import nidn\n",
+    "import fdtd\n",
+    "import fdtd.backend as bd\n",
+    "from nidn.trcwa.init_trcwa import _init_trcwa"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "fdtd.set_backend(\"torch\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "cfg = nidn.load_default_cfg()\n",
+    "\n",
+    "WAVELENGTH = 5.35e-06\n",
+    "\n",
+    "GRID_SPACING = cfg.physical_wavelength_range[0]*0.1\n",
+    "GRID_SIZE_X = 6e-6\n",
+    "GRID_SIZE_Y = GRID_SPACING * 50 # optimal value to be investigated \n",
+    "TRANSMISSION_DETECTOR_X = int(3.6*10**(-6)/(GRID_SPACING))\n",
+    "REFLECTION_DETECTOR_X = int(2.4*10**(-6)/(GRID_SPACING))\n",
+    "SOURCE_X = int(1.6*10**(-6)/(GRID_SPACING))\n",
+    "SOURCE_Y = GRID_SIZE_Y/2\n",
+    "PML_THICKNESS = int(1.5*10**(-6)/(GRID_SPACING))\n",
+    "OBJECT_START_X = int(2.5*10**(-6)/(GRID_SPACING))\n",
+    "OBJECT_END_X = int(3.5*10**(-6)/(GRID_SPACING))\n",
+    "PULSE_SOURCE = False\n",
+    "SPEED_LIGHT: float = 299_792_458.0  # [m/s] speed of light"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "grid = fdtd.Grid(\n",
+    "    (GRID_SIZE_X, GRID_SIZE_Y, 1),\n",
+    "    grid_spacing=GRID_SPACING,\n",
+    "    permittivity=1.0,\n",
+    "    permeability=1.0\n",
+    ")\n",
+    "\n",
+    "# grid[0, :, :] = fdtd.PeriodicBoundary(name=\"xbounds\")\n",
+    "grid[0:PML_THICKNESS, :, :] = fdtd.PML(name=\"pml_xlow\")\n",
+    "grid[-PML_THICKNESS:, :, :] = fdtd.PML(name=\"pml_xhigh\")\n",
+    "\n",
+    "grid[:, 0, :] = fdtd.PeriodicBoundary(name=\"ybounds\")\n",
+    "#grid[:, 0:10, :] = fdtd.PML(name=\"pml_ylow\")\n",
+    "#grid[:, -10:, :] = fdtd.PML(name=\"pml_yhigh\")\n",
+    "\n",
+    "point = True\n",
+    "\n",
+    "if(point):\n",
+    "    grid[SOURCE_X,SOURCE_Y, 0] = fdtd.PointSource(\n",
+    "    period=WAVELENGTH / SPEED_LIGHT, name=\"linesource\",\n",
+    "    pulse =PULSE_SOURCE,\n",
+    "    cycle=1,\n",
+    "    hanning_dt=1e-15)\n",
+    "else:\n",
+    "        grid[SOURCE_X,:, 0] = fdtd.LineSource(\n",
+    "    period=WAVELENGTH / SPEED_LIGHT, name=\"linesource\")\n",
+    "\n",
+    "\n",
+    "\n",
+    "transmisssion_detector = fdtd.LineDetector(name=\"t_detector\")\n",
+    "reflection_detector = fdtd.LineDetector(name=\"r_detector\")\n",
+    "grid[TRANSMISSION_DETECTOR_X, :, 0] =transmisssion_detector\n",
+    "grid[REFLECTION_DETECTOR_X,:,0] = reflection_detector\n",
+    "\n",
+    "#grid[20:30,:, 0:1] = fdtd.AnisotropicObject(permittivity=2.5, name=\"object\")\n",
+    "\n",
+    "grid.run(300, progress_bar=False)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "<Figure size 432x288 with 0 Axes>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "image/png": "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L5vNIp/PU5CsV1999ZS3v/3t+1etWrV5w4YNze985ztnOXEBbUI33HDDy+eee26/GPfYY49t+PnPfz7qkksumf7JT35yxyc+8YnXg6+6TklZF4wnC1YiZjeeC+eJ2c0ikClQSheHmEnQGJ0CPXs8C4+sI5vsSVZpgXxYWA+QlsvEA79myR+7V8WNKjzPvC/AqwFLot12C9KqgZJ7o+yaVJqxWE5cQnZsyDJCLuX11j31qaflwgbICABNf93kHie1IdGpp57af8MNN0z8j//4j5czmQx+//vft5188smB2twpp5xy4Pbbbx+7fPny/WvWrGnZvn178/HHH3/ECV+2bNn+P//5z60vvPBCu5h3yZIl/eedd96Ma665ZsekSZMKO3bsyKq0ZQf//d//PaK7u3sAABYsWHDw1ltvHfPxj398z3e/+92xixYtOgAAxxxzzOCTTz7Zfumll+798Y9/PNohXhVOOOGEI6+++mrzc8891zJnzpyBn/70p2OduP7+/uzUqVMHAeC73/3u+KByHJxxxhn7br755q6lS5fub2lpYWvWrGnp7u4eeu2113LTp08fvOqqq3YfPHgw89RTT7UDGJ6kHKS8iUuAi+mZl5j5suz/eGKW3VEGfVNGqdxgU0bperwE49WmZdfvt4fyf/3p1XmdBDLNWadsHiIPO4Hk1MG1lTNS4IlZbEO3XqHdPJoz33ayF5NETp+GLJxrE7JQpsrvWQfV0KS/9rWvbbvsssum9fb29jHGaOrUqQOPPvropqA8n/3sZ3d+4AMfOKanp6cvm83iu9/97pa2tjb26U9/euf73ve+6T09PX1z5sw5NG/ePN8npRYtWnTkqquu2r548eLeTCbD5s6de+jnP//5FjGdY1O2LAuTJ08e/M///M8tAHDzzTe/fPHFF3d/+9vfnjRu3Lj8D3/4wy0AcMUVV+xaunTpjHnz5s1+29ve1t/W1ha0PQ7a29vZv/3bv720dOnSGWPHjs2/+c1vPrBu3bo2ALj66qtfu/TSS6evXLly0uLFi32arwyf+tSndm/ZsqVl3rx5sxljNHbs2KH7779/80MPPTRi5cqVk3K5HGtvby/8+Mc//qtOeXW5dee22+/VyidOpCk/6UTClp4E4dz7bThXe6bSOXnyleIzHgGEeKm88pd8mBub7iQVH+YbfnsZyl+HRC63Tbhzj02e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",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "plt.figure()\n",
+    "grid.visualize(z=0, animate = True)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "transmission_output = transmisssion_detector.detector_values()\n",
+    "reflection_output = reflection_detector.detector_values()\n",
+    "z_vals_t = [e[int(SOURCE_Y)][2] for e in transmission_output['E']]\n",
+    "z_vals_r = [e[int(SOURCE_Y)][2] for e in reflection_output['E']]\n",
+    "t = [i for i in range(len(z_vals_t))]\n",
+    "plt.plot(t,z_vals_t)\n",
+    "plt.plot(t,z_vals_r)\n",
+    "plt.show()\n",
+    "\n",
+    "intensity1 = 0\n",
+    "for i in z_vals_t:\n",
+    "    intensity1 += i**2\n",
+    "intensity1 = intensity1/len(z_vals_t)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "grid2 = fdtd.Grid(\n",
+    "    (GRID_SIZE_X, GRID_SIZE_Y, 1),\n",
+    "    grid_spacing=GRID_SPACING,\n",
+    "    permittivity=1.0,\n",
+    "    permeability=1.0\n",
+    ")\n",
+    "\n",
+    "# grid[0, :, :] = fdtd.PeriodicBoundary(name=\"xbounds\")\n",
+    "grid2[0:PML_THICKNESS, :, :] = fdtd.PML(name=\"pml_xlow\")\n",
+    "grid2[-PML_THICKNESS:, :, :] = fdtd.PML(name=\"pml_xhigh\")\n",
+    "\n",
+    "grid2[:, 0, :] = fdtd.PeriodicBoundary(name=\"ybounds\")\n",
+    "#grid2[:, 0:10, :] = fdtd.PML(name=\"pml_ylow\")\n",
+    "#grid2[:, -10:, :] = fdtd.PML(name=\"pml_yhigh\")\n",
+    "\n",
+    "point = True\n",
+    "\n",
+    "if(point):\n",
+    "    grid2[SOURCE_X,SOURCE_Y, 0] = fdtd.PointSource(\n",
+    "    period=WAVELENGTH / SPEED_LIGHT, name=\"linesource\",\n",
+    "    pulse = PULSE_SOURCE,\n",
+    "    cycle=1,\n",
+    "    hanning_dt=1e-15)\n",
+    "else:\n",
+    "    grid2[SOURCE_X,:, 0] = fdtd.LineSource(\n",
+    "    period=WAVELENGTH / SPEED_LIGHT, name=\"linesource\")\n",
+    "\n",
+    "\n",
+    "\n",
+    "transmisssion_detector2 = fdtd.LineDetector(name=\"t_detector\")\n",
+    "reflection_detector2 = fdtd.LineDetector(name=\"r_detector\")\n",
+    "grid2[TRANSMISSION_DETECTOR_X, :, 0] =transmisssion_detector2\n",
+    "grid2[REFLECTION_DETECTOR_X,:,0] = reflection_detector2\n",
+    "\n",
+    "grid2[OBJECT_START_X:OBJECT_END_X,:, :] = fdtd.AnisotropicObject(permittivity=5.1984, name=\"object\")\n",
+    "\n",
+    "grid2.run(300, progress_bar=False)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "<Figure size 432x288 with 0 Axes>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "image/png": "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CBJk38Y8rjB5yMJ5I2a5r5xSl/fGKpu6s6enp+vpp58esWzZsrFWGtq0aVM9AMybN6+vra3NFXL485//3HzNNdfsBIDZs2cfGT9+/MDq1auHvPDCC82f//znd1rlH+7o6Dgk5n366aePWrhw4Xvjxo1LA4CsfMAMX/zsZz97yzAMXH755ZNuuummsf/+7/++45VXXhn65JNPbgaAT3/603tuvvnmiUHHPXPmzIPHHXfcIABMnz790ObNm+uHDRuWmThxYv/MmTP7AeCyyy57984772wFgD179iQ//OEPT96yZcsQImKDg4PZE9OrTp555pmj1q9f3/Too4+OBID9+/cn165dO+Tkk08+ePXVV7cPDg4mLr744vf+4R/+4bCYV0Y8RZm5v8vEiMh8lLTFKid9yH7j57IgxpDtwMQJLQMhoSLMtiEewmyvkAkzLFtkwhzVxZxPOar7d/VF5m42pYh8iILK2yFNzwmp2DbgWCeEnzwFWeY9i+WW8Y4pm7qTMYYHHnhg06xZs/r59S+88MLQpqYmQ1aOX0Ow0oyLFPQ62RyJRAKLFi3ae9ttt43xS5dKpVgmY2qlYRjghbShoSG7v2QyiXQ6TX62Xn/99RM+8IEP7F++fPnmDRs21J9xxhmd9jafOqGlS5e+ddFFF/WJ255//vkNv/3tb4dfccUVkz//+c/3fu5zn3vX/6irQJSz66QJBe+RUxhHf2I+hGAt83myYh0gzBDK9BwcIdjgdyylvIyl3qSiITLP3mv+EFmeYoyC9POOZWnCCjKzk/gIMu9BA8DRL7/i3L/isaTe2JT9HtWERKeffnrf0qVL237605++lUgk8Kc//anx1FNP9fXmTjvttAP33ntvy6JFi/avWrWqYfv27fXHH3/8EXv9woUL97/00ktDXn/99SYx7/z58/suvvjiKTfccEPv2LFjM729vUkvb9nmj3/847D29vZ+AJg9e/bBO++8c+RnP/vZPT/+8Y9benp6DgDAMcccM7By5cqmK6+88r1f/OIXI2zh9eKEE0448s4779S/9tprDdOnT+//9a9/3WJv6+vrS06cOHEAAH784x+P9ivH5uyzz953++23ty5YsGB/Q0MDW7VqVUN7e/vgjh07UpMnTx647rrrdh88eDDx8ssvNwGoUlEOkc7r15GFEvw22hepLA9jTo9Z5ukS3GIt7qZQ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",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "plt.figure()\n",
+    "grid2.visualize(z=0, animate = True)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "transmission_output2 = transmisssion_detector2.detector_values()\n",
+    "reflection_output2 = reflection_detector2.detector_values()\n",
+    "z_vals_t2 = [e[int(SOURCE_Y)][2] for e in transmission_output2['E']]\n",
+    "z_vals_r2 = [e[int(SOURCE_Y)][2] for e in reflection_output2['E']]\n",
+    "t = [i for i in range(len(z_vals_t2))]\n",
+    "plt.plot(t,z_vals_t2)\n",
+    "#plt.plot(t,z_vals_r2)\n",
+    "plt.show()\n",
+    "hx_trans2 = [e[int(SOURCE_Y)][0] for e in transmission_output2['H']]\n",
+    "hy_trans2 = [e[int(SOURCE_Y)][1] for e in transmission_output2['H']]\n",
+    "\n",
+    "plt.plot(t,z_vals_t2)\n",
+    "plt.plot(t,z_vals_t)\n",
+    "plt.legend([\"Transmitted signal whith object\",\"Transmitted signal free space\"])\n",
+    "plt.show()\n",
+    "intensity2 = 0.00\n",
+    "for i in z_vals_t2:\n",
+    "    intensity2 += i**2\n",
+    "intensity2 = intensity2/len(z_vals_t2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "intensity2 = 0.00\n",
+    "for i in z_vals_t2:\n",
+    "    intensity2 += i**2\n",
+    "intensity2 = intensity2/len(z_vals_t2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "tensor(0.4514)"
+      ]
+     },
+     "execution_count": 11,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "transmission = intensity2/intensity1\n",
+    "transmission"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[<matplotlib.lines.Line2D at 0x1f9e8dfd310>]"
+      ]
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    },
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "plt.plot(t,z_vals_t)\n",
+    "plt.plot(t,z_vals_t2)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import numpy"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Correct phase shift"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "signal1 = z_vals_t\n",
+    "signal2 = z_vals_t2\n",
+    "max_phase_offset = 300\n",
+    "max_corr = 0\n",
+    "best_offset = 0\n",
+    "for offset in range(max_phase_offset):\n",
+    "    offset_sig = signal1[offset:] + signal1[:offset] # phase shift signal with concat  \n",
+    "    correlation = sum(sum(numpy.corrcoef(offset_sig,signal2)))\n",
+    "    if correlation > max_corr:\n",
+    "      max_corr = correlation \n",
+    "      best_offset = offset \n",
+    "#phasedshifted_sig = signal1[best_offset :] + signal1[:best_offset ] # phase shift signal with concat\n",
+    "phasedshifted_sig = [0  for i in range(300-best_offset)] + signal1[:best_offset ]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[<matplotlib.lines.Line2D at 0x1f9e8e3a0d0>]"
+      ]
+     },
+     "execution_count": 15,
+     "metadata": {},
+     "output_type": "execute_result"
+    },
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "plt.plot(t,phasedshifted_sig)\n",
+    "plt.plot(t,signal2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "tensor(0.4942)"
+      ]
+     },
+     "execution_count": 16,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "intensity1 = 0\n",
+    "for i in signal2:\n",
+    "    intensity1 += i**2\n",
+    "intensity1 = intensity1/len(phasedshifted_sig)\n",
+    "intensity2 = 0\n",
+    "for i in phasedshifted_sig:\n",
+    "    intensity2 += i**2\n",
+    "intensity2 = intensity2/len(signal2)\n",
+    "\n",
+    "transmission = intensity1/intensity2\n",
+    "transmission"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from torch.fft import rfft, rfftfreq\n",
+    "import torch"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "C:\\Users\\to-bo\\AppData\\Local\\Temp\\ipykernel_60212\\955458584.py:2: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
+      "  signal2 = torch.tensor(signal2)\n"
+     ]
+    },
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "signal1 = torch.tensor(phasedshifted_sig)\n",
+    "signal2 = torch.tensor(signal2)\n",
+    "sample_interval = GRID_SPACING/(numpy.sqrt(2)*SPEED_LIGHT)\n",
+    "yf1 = rfft(signal1)\n",
+    "yf2 = rfft(signal2)\n",
+    "xf = rfftfreq(300, sample_interval)\n",
+    "plt.plot(xf, numpy.abs(yf1))\n",
+    "plt.plot(xf, numpy.abs(yf2))\n",
+    "plt.show()"
+   ]
+  }
+ ],
+ "metadata": {
+  "interpreter": {
+   "hash": "cd0991b29d7d690bc5e205a01d9268c3e1c540c626acb4d966155a50f21eac25"
+  },
+  "kernelspec": {
+   "display_name": "Python 3.9.10 64-bit ('nidn': conda)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.9.10"
+  },
+  "orig_nbformat": 4
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}


Test patch:
diff --git a/nidn/tests/material_collection_test.py b/nidn/tests/material_collection_test.py
index a59787a..0a05e20 100644
--- a/nidn/tests/material_collection_test.py
+++ b/nidn/tests/material_collection_test.py
@@ -3,7 +3,7 @@
 
 def test_material_collection_init():
     """Tests if the material collection can be initialized successfully."""
-    target_frequencies = [9.5,1.0, 0.1, 0.01]
+    target_frequencies = [9.5, 1.0, 0.1, 0.01]
     mc = MaterialCollection(target_frequencies)
     assert len(mc.material_names) > 0
     assert mc.target_frequencies == target_frequencies
diff --git a/nidn/tests/target_frequency_test.py b/nidn/tests/target_frequency_test.py
index c1f0659..dafbe40 100644
--- a/nidn/tests/target_frequency_test.py
+++ b/nidn/tests/target_frequency_test.py
@@ -1,7 +1,7 @@
 from loguru import logger
 
 from ..trcwa.compute_target_frequencies import compute_target_frequencies
-from ..trcwa.constants import TRCWA_UNIT_MAGNITUDE
+from ..utils.global_constants import UNIT_MAGNITUDE
 
 
 def test_conversion():
@@ -18,8 +18,8 @@ def test_conversion():
 
     assert len(target_frequencies) == 5
 
-    prod_min_wl = 1.0 / target_frequencies[-1] * TRCWA_UNIT_MAGNITUDE
-    prod_max_wl = 1.0 / target_frequencies[0] * TRCWA_UNIT_MAGNITUDE
+    prod_min_wl = 1.0 / target_frequencies[-1] * UNIT_MAGNITUDE
+    prod_max_wl = 1.0 / target_frequencies[0] * UNIT_MAGNITUDE
 
     assert abs(prod_min_wl - min_wl) < 1e-8
     assert abs(prod_max_wl - max_wl) < 1e-8
diff --git a/nidn/tests/trcwa_test.py b/nidn/tests/trcwa_test.py
index 41a8e48..4ad44b7 100644
--- a/nidn/tests/trcwa_test.py
+++ b/nidn/tests/trcwa_test.py
@@ -3,7 +3,7 @@
 from dotmap import DotMap
 import sys
 
-from ..trcwa.compute_spectrum import compute_spectrum
+from ..utils.compute_spectrum import compute_spectrum
 
 _TRCWA_TEST_TOLERANCE = 1e-7
 torch.set_printoptions(precision=12)
@@ -21,7 +21,8 @@ def test_single_layer():
     run_cfg.N_freq = 1
     run_cfg.TRCWA_L_grid = [[1.0, 0.0], [0.0, 1.0]]
     run_cfg.TRCWA_NG = 11
-    run_cfg.TRCWA_PER_LAYER_THICKNESS = [1.0]
+    run_cfg.PER_LAYER_THICKNESS = [1.0]
+    run_cfg.solver = "TRCWA"
 
     # Get eps shape
     shape = [
@@ -32,13 +33,10 @@ def test_single_layer():
     ]
 
     # Get a grid of 1 + 1j
-    eps_grid = (
-        torch.ones(
-            shape,
-            dtype=torch.cfloat,
-        )
-        * (1.0 + 1j)
-    )
+    eps_grid = torch.ones(
+        shape,
+        dtype=torch.cfloat,
+    ) * (1.0 + 1j)
 
     logger.debug("Computing spectrum...")
 
@@ -66,7 +64,8 @@ def test_uniform_layer():
     run_cfg.N_freq = 2
     run_cfg.TRCWA_L_grid = [[1.0, 0.0], [0.0, 1.0]]
     run_cfg.TRCWA_NG = 11
-    run_cfg.TRCWA_PER_LAYER_THICKNESS = [1.0]
+    run_cfg.PER_LAYER_THICKNESS = [1.0]
+    run_cfg.solver = "TRCWA"
 
     # Get eps shape
     shape = [
@@ -113,7 +112,8 @@ def test_three_layer():
     run_cfg.N_freq = 1
     run_cfg.TRCWA_L_grid = [[1.0, 0.0], [0.0, 1.0]]
     run_cfg.TRCWA_NG = 11
-    run_cfg.TRCWA_PER_LAYER_THICKNESS = [1.0]
+    run_cfg.PER_LAYER_THICKNESS = [1.0]
+    run_cfg.solver = "TRCWA"
 
     # Get eps shape
     shape = [
@@ -124,13 +124,10 @@ def test_three_layer():
     ]
 
     # Get a somewhat interesting grid
-    eps_grid = (
-        torch.ones(
-            shape,
-            dtype=torch.cfloat,
-        )
-        * (-4.2 + 0.42j)
-    )
+    eps_grid = torch.ones(
+        shape,
+        dtype=torch.cfloat,
+    ) * (-4.2 + 0.42j)
 
     eps_grid[0:3, 0:3, 0, :] = eps_grid[0:3, 0:3, 0, :] * 1.0
     eps_grid[0:3, 0:3, 1, :] = eps_grid[0:3, 0:3, 1, :] * 2.0
diff --git a/notebooks/fdtd_integration_test.ipynb b/notebooks/fdtd_integration_test.ipynb
new file mode 100644
index 0000000..7773108
--- /dev/null
+++ b/notebooks/fdtd_integration_test.ipynb
@@ -0,0 +1,100 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "### Imports\n",
+    "%load_ext autoreload\n",
+    "%autoreload 2\n",
+    "\n",
+    "import sys\n",
+    "sys.path.append(\"../\")\n",
+    "import nidn"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "cfg = nidn.load_default_cfg()\n",
+    "cfg.N_layers = 1\n",
+    "t,r = nidn.FDTD_compute_spectrum(cfg,[5.1984,2,3,4,5,6,7,8])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from nidn.scripts.compute_fdtd_spectrum import plot_fdtd_spectrum\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# The spectrum from the script implementation\n",
+    "plot_fdtd_spectrum(cfg)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#The spectrum from the fdtd_int implementation\n",
+    "nidn.plot_spectra(cfg,prod_R_spectrum=r, prod_T_spectrum=t)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "nidn.plot_spectrum(cfg,r,t)"
+   ]
+  }
+ ],
+ "metadata": {
+  "interpreter": {
+   "hash": "cd0991b29d7d690bc5e205a01d9268c3e1c540c626acb4d966155a50f21eac25"
+  },
+  "kernelspec": {
+   "display_name": "Python 3.9.10 ('nidn')",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.9.10"
+  },
+  "orig_nbformat": 4
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}