Skip to content
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

WI add tests #54

Merged
merged 8 commits into from
Mar 3, 2022
36 changes: 36 additions & 0 deletions nidn/tests/fdtd_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import torch

from ..fdtd_integration.init_fdtd import init_fdtd
torbjornstoro marked this conversation as resolved.
Show resolved Hide resolved
from ..materials.layer_builder import LayerBuilder
from ..trcwa.compute_target_frequencies import compute_target_frequencies
from ..utils.load_default_cfg import load_default_cfg
from ..utils.compute_spectrum import compute_spectrum


def test_fdtd_simulation():
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please write brief docstrings for each test describing what is tested, see e.g. here

"""Tests a single uniform layer at two frequencies. TRCWA vs. GRCWA"""

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite the difference between this test and the init_fdtd_grid_test?

Maybe just make it one test called fdtd_test?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think fdtd_test can then have several subtests
test_init
uniform layer
4 uni
patterned

# Create grid with uniform layer
cfg = load_default_cfg()
cfg.N_layers = 1
cfg.N_freq = 1
eps_grid = torch.zeros(1, 1, cfg.N_layers, cfg.N_freq, dtype=torch.cfloat)
cfg.Nx = 1
cfg.Ny = 1
# Note: something went wrong when smalles wavelength was 1e-5, guess its the grid scaling
gomezzz marked this conversation as resolved.
Show resolved Hide resolved
cfg.physical_wavelength_range[0] = 1e-6
cfg.physical_wavelength_range[1] = 2e-6
cfg.target_frequencies = compute_target_frequencies(
cfg.physical_wavelength_range[0],
cfg.physical_wavelength_range[1],
cfg.N_freq,
"linear",
)
cfg.solver = "FDTD"
layer_builder = LayerBuilder(cfg)
eps_grid[:, :, 0, :] = layer_builder.build_uniform_layer("titanium_oxide")
transmission_spectrum, reflection_spectrum = compute_spectrum(eps_grid, cfg)
assert sum(transmission_spectrum) > 0
assert sum(reflection_spectrum) > 0
gomezzz marked this conversation as resolved.
Show resolved Hide resolved


if __name__ == "__main__":
test_fdtd_simulation()
82 changes: 82 additions & 0 deletions nidn/tests/init_fdtd_grid_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import torch

from ..fdtd_integration.init_fdtd import init_fdtd
from ..materials.layer_builder import LayerBuilder
from ..trcwa.compute_target_frequencies import compute_target_frequencies
from ..utils.load_default_cfg import load_default_cfg


def test_single_uniform_layer():
torbjornstoro marked this conversation as resolved.
Show resolved Hide resolved
# Create grid with uniform layer
cfg = load_default_cfg()
cfg.N_layers = 1
cfg.N_freq = 1
torbjornstoro marked this conversation as resolved.
Show resolved Hide resolved
eps_grid = torch.zeros(1, 1, cfg.N_layers, cfg.N_freq, dtype=torch.cfloat)
cfg.Nx = 1
cfg.Ny = 1
# Note: something went wrong when smalles wavelength was 1e-5, guess its the grid scaling
cfg.physical_wavelength_range[0] = 1e-6
cfg.physical_wavelength_range[1] = 2e-6
cfg.target_frequencies = compute_target_frequencies(
cfg.physical_wavelength_range[0],
cfg.physical_wavelength_range[1],
cfg.N_freq,
"linear",
)
layer_builder = LayerBuilder(cfg)
eps_grid[:, :, 0, :] = layer_builder.build_uniform_layer("titanium_oxide")
grid, transmission_detector, reflection_detetctor = init_fdtd(
cfg, include_object=True, wavelength=1e-5, permittivity=eps_grid
torbjornstoro marked this conversation as resolved.
Show resolved Hide resolved
)
# Check that it was made properly
assert len(grid.objects) == 1
assert grid.objects[0].permittivity == eps_grid[0, 0, 0, 0].real
assert len(grid.detectors) == 2
assert len(grid.sources) == 1
assert len(grid.boundaries) >= 2
gomezzz marked this conversation as resolved.
Show resolved Hide resolved


def test_multiple_uniform_layers():
# Create grid with multiple uniform layer
cfg = load_default_cfg()
cfg.N_layers = 4
cfg.N_freq = 1
eps_grid = torch.zeros(1, 1, cfg.N_layers, cfg.N_freq, dtype=torch.cfloat)
cfg.Nx = 1
cfg.Ny = 1
cfg.physical_wavelength_range[
0
] = 1e-6 # Note: something went wrong when smalles wavelength was 1e-5, guess its the grid scaling
torbjornstoro marked this conversation as resolved.
Show resolved Hide resolved
cfg.physical_wavelength_range[1] = 2e-6
cfg.target_frequencies = compute_target_frequencies(
cfg.physical_wavelength_range[0],
cfg.physical_wavelength_range[1],
cfg.N_freq,
"linear",
)
layer_builder = LayerBuilder(cfg)
eps_grid[:, :, 0, :] = layer_builder.build_uniform_layer("titanium_oxide")
eps_grid[:, :, 1, :] = layer_builder.build_uniform_layer("zirconium")
eps_grid[:, :, 2, :] = layer_builder.build_uniform_layer("gallium_arsenide")
eps_grid[:, :, 3, :] = layer_builder.build_uniform_layer("silicon_nitride")
grid, transmission_detector, reflection_detetctor = init_fdtd(
cfg, include_object=True, wavelength=1e-5, permittivity=eps_grid
)
# Check that it was made properly
assert len(grid.objects) == 4
for i in range(4):
assert grid.objects[i].permittivity == eps_grid[0, 0, i, 0].real
assert len(grid.detectors) == 2
assert len(grid.sources) == 1
# If periodic boundaries in both x and y, it is two, if pml in x and periodic in y there is 3 and 4 if pml in both directions (I think)
assert len(grid.boundaries) >= 2


def test_single_patterned_layer():
# TODO: Test patterned layer, must be implemented first
pass


if __name__ == "__main__":
test_single_uniform_layer()
test_multiple_uniform_layers()
74 changes: 62 additions & 12 deletions nidn/training/utils/validate_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,17 @@ def _validate_config(cfg: DotMap):
"reg_loss_weight",
"add_noise",
"noise_scale",
"solver",
"TRCWA_L_grid",
"TRCWA_NG",
"FDTD_grid",
"FDTD_use_pointsource",
"FDTD_use_pulsesource",
"FDTD_pml_thickness",
"FDTD_source",
"FDTD_free_space_distance",
"FDTD_reflection_detector_x",
"FDTD_niter",
"target_reflectance_spectrum",
"target_transmittance_spectrum",
"freq_distribution",
Expand All @@ -60,6 +69,7 @@ def _validate_config(cfg: DotMap):
"eps_oversampling",
"seed",
"TRCWA_NG",
"FDTD_niter",
]
float_keys = [
"L",
Expand All @@ -70,12 +80,24 @@ def _validate_config(cfg: DotMap):
"siren_omega",
"noise_scale",
"reg_loss_weight",
"FDTD_free_space_distance",
"FDTD_reflection_detector_x",
"FDTD_pml_thickness",
]
boolean_keys = ["use_regularization_loss", "add_noise", "use_gpu", "avoid_zero_eps"]
string_keys = ["model_type", "type", "name", "freq_distribution"]
boolean_keys = [
"use_regularization_loss",
"add_noise",
"use_gpu",
"avoid_zero_eps",
"FDTD_use_pulsesource",
"FDTD_use_pointsource",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aren't these mutually exclusive? If so, shouldn't rather be something like FDTD_source_type = "pulse" or "point" ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the pulse is about continuous wave or not. point is about pointsource or linesource, both which can be continuous or have a pulse. But I can change the naming/structure for clarity

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, well depends on the logic behind. "use_pointsource" to me sounds as if it is true I use a point source, otherwise I use none.

If it is like that fine, otherwise it should probably be sourcetype with FDTD_source_type="point" or "line"

Analogously for pulse

]
string_keys = ["model_type", "type", "name", "freq_distribution", "solver"]
list_keys = [
"PER_LAYER_THICKNESS",
"TRCWA_L_grid",
"FDTD_grid",
"FDTD_source",
"target_reflectance_spectrum",
"target_transmittance_spectrum",
"physical_wavelength_range",
Expand Down Expand Up @@ -111,6 +133,14 @@ def _validate_config(cfg: DotMap):
if not (cfg.physical_wavelength_range[0] < cfg.physical_wavelength_range[1]):
raise ValueError(f"physical_wavelength_range must be ordered from low to high")

if (
cfg.FDTD_pml_thickness + cfg.FDTD_free_space_distance
< cfg.FDTD_reflection_detector_x
) or (cfg.FDTD_reflection_detector_x < cfg.FDTD_pml_thickness):
raise ValueError(
f"Reflection detector must be placed in the free space before an eventual object, and after the pml layer"
)

positive_value_keys = [
"L",
"n_neurons",
Expand All @@ -124,6 +154,10 @@ def _validate_config(cfg: DotMap):
"noise_scale",
"TRCWA_NG",
"reg_loss_weight",
"FDTD_niter",
"FDTD_free_space_distance",
"FDTD_reflection_detector_x",
"FDTD_pml_thickness",
]
for key in positive_value_keys:
if not (cfg[key] > 0):
Expand All @@ -142,24 +176,32 @@ def _validate_config(cfg: DotMap):
if not cfg.TRCWA_L_grid[0][0] > cfg.TRCWA_L_grid[0][1]:
raise ValueError(f"TRCWA_L_grid dim0 must be ordered from high to low")

if not all(cfg.TRCWA_L_grid) >= 0:
raise ValueError(f"TRCWA_L_grid must be positive")

if not all(cfg.target_transmittance_spectrum) >= 0:
raise ValueError(f"target_transmittance_spectrum must be positive")
all_positive_list_keys = [
"TRCWA_L_grid",
"PER_LAYER_THICKNESS",
"FDTD_grid",
"FDTD_source",
torbjornstoro marked this conversation as resolved.
Show resolved Hide resolved
]
all_positive_or_zero_list_keys = [
"target_transmittance_spectrum",
"target_reflectance_spectrum",
]

if not all(cfg.target_reflectance_spectrum) >= 0:
raise ValueError(f"target_reflectance_spectrum must be positive")
for key in all_positive_list_keys:
if not (all(cfg[key]) > 0.0):
raise ValueError(f"All elements in {key} must be a positive integer")
for key in all_positive_or_zero_list_keys:
if not (all(cfg[key]) >= 0.0):
raise ValueError(
f"All elements in {key} must be a positive integer or zero"
)

if not len(cfg.target_transmittance_spectrum) == cfg.N_freq:
raise ValueError(f"target_transmittance_spectrum must have length N_freq")

if not len(cfg.target_reflectance_spectrum) == cfg.N_freq:
raise ValueError(f"target_reflectance_spectrum must have length N_freq")

if not (all(cfg.TRCWA_PER_LAYER_THICKNESS) > 0.0):
raise ValueError(f"thickness must a positive number.")

if not (
len(cfg.PER_LAYER_THICKNESS) == cfg.N_layers
or len(cfg.PER_LAYER_THICKNESS) == 1
Expand All @@ -168,3 +210,11 @@ def _validate_config(cfg: DotMap):

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

if not len(cfg.FDTD_grid) == 3:
raise ValueError(f"FDTD_grid must me 3-dimentional")

if not (len(cfg.FDTD_source) == 2 or len(cfg.FDTD_source) == 3):
raise ValueError(
f"The FDTD source needs either 2- or 3-dimensional coordinaets"
torbjornstoro marked this conversation as resolved.
Show resolved Hide resolved
)
4 changes: 2 additions & 2 deletions nidn/utils/resources/default_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ imag_min_eps = 0.0
imag_max_eps = 3.0

# Simulation type
solver = "FDTD" # Options: FDTD, TRCWA
solver = "TRCWA" # Options: FDTD, TRCWA

# Grid dimensions
Nx = 1
Expand All @@ -48,7 +48,7 @@ FDTD_use_pointsource = false # If the source should be a point source in the FDT
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
torbjornstoro marked this conversation as resolved.
Show resolved Hide resolved
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_free_space_distance = 1.0 # 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

Expand Down