-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added timestep check #111
Added timestep check #111
Changes from all commits
33076b0
42cea44
71eb23e
dc799d5
e7e66b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import torch | ||
from .constants import FDTD_GRID_SCALE | ||
from ..utils.global_constants import UNIT_MAGNITUDE | ||
|
||
|
||
def _compute_fdtd_grid_scaling(cfg): | ||
"""Compute the scaling of the FDTD grid | ||
|
||
Args: | ||
cfg (DotMap): Run config | ||
|
||
Returns: | ||
torch.float: The scaling is the number of grid points per unit magnitude. This is the maximum of the relation 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 are too few grid points for certain elements to be placed correctly. | ||
""" | ||
return torch.maximum( | ||
torch.tensor( | ||
UNIT_MAGNITUDE / (cfg.physical_wavelength_range[0] * FDTD_GRID_SCALE) | ||
), | ||
torch.tensor(cfg.FDTD_min_gridpoints_per_unit_magnitude), | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
import torch | ||
|
||
from nidn.fdtd_integration.constants import FDTD_GRID_SCALE | ||
from nidn.fdtd_integration.compute_fdtd_grid_scaling import _compute_fdtd_grid_scaling | ||
from nidn.utils.global_constants import UNIT_MAGNITUDE | ||
|
||
from ..trcwa.get_frequency_points import get_frequency_points | ||
|
@@ -31,9 +32,17 @@ def compute_spectrum_fdtd(permittivity, cfg: DotMap): | |
logger.debug(physical_wavelengths) | ||
logger.debug("Number of layers: " + str(len(permittivity[0, 0, :, 0]))) | ||
|
||
if (len(cfg.PER_LAYER_THICKNESS) == 1) and (cfg.N_layers > 1): | ||
cfg.PER_LAYER_THICKNESS = cfg.PER_LAYER_THICKNESS * cfg.N_layers | ||
|
||
cfg.FDTD_grid_scaling = _compute_fdtd_grid_scaling(cfg) | ||
# 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): | ||
|
||
_check_if_enough_timesteps( | ||
cfg, physical_wavelengths[i], permittivity[:, :, :, i] | ||
) | ||
logger.debug("Simulating for wavelenght: {}".format(physical_wavelengths[i])) | ||
transmission_signal = [] | ||
reflection_signal = [] | ||
|
@@ -153,3 +162,57 @@ def _average_along_detector(signal): | |
s[2] += p[2] / len(signal[i]) | ||
avg[i] = s | ||
return avg | ||
|
||
|
||
def _summed_thickness_times_sqrt_permittivity(thicknesses, permittivity): | ||
""" | ||
Helper function to calculate the sum of the product of the thickness and | ||
the square root of the permittivity for each layer in a material stack. | ||
|
||
Args: | ||
thicknesses (tensor): tensor with the thickness of each layer of the material stack | ||
permittivity (tensor): tensor with the relative permittivity for each layer of the material stack | ||
|
||
Returns: | ||
float: sum of thickness times sqrt(e_r) for each layer | ||
""" | ||
summed_permittivity = 0 | ||
for i in range(len(thicknesses)): | ||
summed_permittivity += thicknesses[i] * torch.sqrt(permittivity.real.max()) | ||
return summed_permittivity | ||
|
||
|
||
def _check_if_enough_timesteps(cfg: DotMap, wavelength, permittivity): | ||
""" | ||
Function to find the recommended minimum number of timesteps. | ||
The signal should have passed trough the material, been reflected to the start of the material and reflected again to the | ||
rear detector before the signal is assumed to be steady state. The max permittivity is used for all layers, in case of patterned layers in the future. | ||
|
||
Args: | ||
cfg (DotMap): config | ||
wavelength (float): wavelength of the simulation | ||
permittivity (tensor): tensor of relative permittivities for each layer | ||
""" | ||
wavelengths_of_steady_state_signal = 5 | ||
number_of_internal_reflections = 3 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also comment here, this is an assumption I guess? Would it be different for more layers, thicker layers e.g.? |
||
recommended_timesteps = int( | ||
( | ||
( | ||
cfg.FDTD_free_space_distance | ||
+ number_of_internal_reflections | ||
* _summed_thickness_times_sqrt_permittivity( | ||
cfg.PER_LAYER_THICKNESS, permittivity | ||
) | ||
+ wavelengths_of_steady_state_signal * wavelength / UNIT_MAGNITUDE | ||
) | ||
* torch.sqrt(torch.tensor(2.0)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where does the sqrt(2) come from? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Courant number |
||
* cfg.FDTD_grid_scaling | ||
).item() | ||
) | ||
logger.debug("Minimum recomended timesteps: {}".format(recommended_timesteps)) | ||
if cfg.FDTD_niter < recommended_timesteps: | ||
logger.warning( | ||
"The number of timesteps should be increased to minimum {} to ensure that the result from the simulation remains physically accurate.".format( | ||
recommended_timesteps | ||
) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you add a comment? I don't get what you mean? the number of wavelengths isn't fixed after all? Do you mean the number of oscillation cycles we want in the signal? Then maybe target_nr_of_steady_cycles or so would be better?