Skip to content

Commit

Permalink
Merge pull request #78 from esa/WI_notebook_examples
Browse files Browse the repository at this point in the history
Added example notebooks for FDTD, one how to use on its own, and one …
  • Loading branch information
torbjornstoro authored Apr 22, 2022
2 parents 9f76397 + 14c115d commit f0ec337
Show file tree
Hide file tree
Showing 9 changed files with 650 additions and 885 deletions.
18 changes: 15 additions & 3 deletions nidn/fdtd/sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def __init__(
pulse: bool = False,
cycle: int = 5,
hanning_dt: float = 10.0,
signal_type: str = "continuous",
):
"""Create a LineSource with a gaussian profile
Expand All @@ -59,6 +60,8 @@ def __init__(
self.cycle = cycle
self.frequency = 1.0 / period
self.hanning_dt = hanning_dt if hanning_dt is not None else 0.5 / self.frequency
self.wavelength = SPEED_OF_LIGHT / self.frequency
self.signal_type = signal_type

def _register_grid(self, grid: Grid, x: Number, y: Number, z: Number):
"""Register a grid for the source.
Expand Down Expand Up @@ -90,12 +93,13 @@ def _register_grid(self, grid: Grid, x: Number, y: Number, z: Number):
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)
self.courant = self.grid.courant_number
self.grid_points_per_wavelength = self.wavelength / self.grid.grid_spacing

def update_E(self):
"""Add the source to the electric field"""
q = self.grid.time_steps_passed
# if pulse
if self.pulse:
if self.signal_type == "hanning":
t1 = int(2 * pi / (self.frequency * self.hanning_dt / self.cycle))
if q < t1:
src = self.amplitude * hanning(
Expand All @@ -104,7 +108,15 @@ def update_E(self):
else:
# src = - self.grid.E[self.x, self.y, self.z, 2]
src = 0
# if not pulse
elif self.signal_type == "ricker":
# By experimental value, the ricker wavelet signal converges to zero after 6 times the grid points per wavelength, so just set the source-signal to zero after this
t1 = self.grid_points_per_wavelength * 6
if q < t1:
vsrcect = self.amplitude * _ricker(
q, self.grid_points_per_wavelength, 1, self.courant
)
else:
src = self.amplitude * 0
else:
src = self.amplitude * sin(2 * pi * q / self.period + self.phase_shift)
self.grid.E[self.x, self.y, self.z, 2] += src
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,6 @@ def _check_for_all_zero_signal(signals):
raise ValueError(
"The free-space signal is all zero. Increase the number of FDTD_niter to ensure that the signal reaches the detector."
)
if _mean_square(signals[1]) <= 1e-15:
logger.warning(
"WARNING:The signal through the material layer(s) never reaches the detector. Increase FDTD_niter to ensure that the signal reaches the detector. The signal usually travels slower in a material than in free space."
)


# From : https://stackoverflow.com/questions/54498775/pytorch-argrelmax-function-or-c
def _torch_find_peaks(signal):
Expand Down
2 changes: 2 additions & 0 deletions nidn/fdtd_integration/init_fdtd.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ def init_fdtd(cfg: DotMap, include_object, wavelength, permittivity):
fdtd:Grid: Grid with all the added object, ready to be run
"""
set_backend("torch")
if (len(cfg.PER_LAYER_THICKNESS) == 1) and (cfg.N_layers > 1):
cfg.PER_LAYER_THICKNESS = [cfg.PER_LAYER_THICKNESS] * cfg.N_layers
# The scaling is the number of grid points per unit magnitude. This is the maximum of the reation between the unit magnitude and 1/10th of the smallest wavelength,
# and a constant which is defaulted to 10. If this scaling becomes too low, i.e. below 2, there might be some errors in creating the grid,
# as there is too feew grid points for ceartian elements to be placed correctly.
Expand Down
5 changes: 0 additions & 5 deletions nidn/training/utils/validate_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,6 @@ def _validate_config(cfg: DotMap):
):
raise ValueError(f"PER_LAYER_THICKNESS must have length 1 or N_layers")

if cfg.solver == "FDTD" and (not len(cfg.PER_LAYER_THICKNESS) == cfg.N_layers):
raise ValueError(
f"PER_LAYER_THICKNESS must have length N_layers when using FDTD"
)

if not (cfg.freq_distribution == "linear" or cfg.freq_distribution == "log"):
raise ValueError(f"freq_distribution must be either 'linear' or 'log'")

Expand Down
Loading

0 comments on commit f0ec337

Please sign in to comment.