# imports
import matplotlib.pylab as plt
import tidy3d as td
from tidy3d import web
td.config.local_cache.enabled = FalseIn this lecture, we will describe the basic concepts of EM simulation using FDTD.
- How Maxwell's equations can be solved computationally in the context of a photonic device.
- Discretization of the simulation space using the finite difference method.
- A demonstration on how we solve for the electromagnetic fields radiated by a dipole source.
This tutorial will walk you through setting up a simple dipole radiation simulation in Tidy3D.
For more details, refer to the Tidy3d documentation.
First we import Tidy3D and the other packages needed. If it is not installed, please perform the installation and account authentication by following the detailed instructions here.
# imports
import matplotlib.pylab as plt
import tidy3d as td
from tidy3d import web
td.config.local_cache.enabled = FalseThen, we will define the basic simulation parameters. Note that the length scale is microns.
# simulation parameters
side_length = 9.0
grid_size = 50e-3
# apply a PML in all directions
boundary_spec = td.BoundarySpec.all_sides(boundary=td.PML())
# spectrum and resolution parameters
lambda0 = 1.0
freq0 = td.C_0 / lambda0
fwidth = freq0 / 50
run_time = 200 / freq0Next, we define the objects present in our simulation, specifically the source and monitor.
# define dipole source at origin pointing in z
dipole_source = td.PointDipole(
center=(0, 0, 0),
source_time=td.GaussianPulse(freq0=freq0, fwidth=fwidth),
polarization="Ez",
name="dipole",
)# define monitor to measure fields in xz plane at central frequency
monitor = td.FieldMonitor(
center=(0, 0, 0),
size=(td.inf, 0, td.inf),
freqs=[freq0],
name="freq_domain",
)And finally, we put everything together in a Simulation object, which contains all of the specs needed to run the simulation.
# define simulation
simulation = td.Simulation(
size=(side_length, side_length, side_length),
grid_spec=td.GridSpec.uniform(dl=grid_size),
structures=[],
sources=[dipole_source],
monitors=[monitor],
run_time=run_time,
boundary_spec=boundary_spec,
)To run the simulation, we will call the web.run() function, passing our Simulation and some parameters about the task name and the path to download the data file.
# run simulation
sim_data = web.run(
simulation, task_name="lecture01_dipole", path="data/data_dipole.hdf5"
)16:02:28 UTC Created task 'lecture01_dipole' with resource_id 'fdve-4324d3d1-499a-4ce0-a79a-d44a1aa46cd7' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-4324d3d1-499 a-4ce0-a79a-d44a1aa46cd7'.
Task folder: 'default'.
Estimated FlexCredit cost: 0.025. This assumes the FDTD solver runs for the full simulation time; if early shutoff is reached, the billed cost can be lower. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
status = queued
To cancel the simulation, use 'web.abort(task_id)' or 'web.delete(task_id)' or abort/delete the task in the web UI. Terminating the Python script will not stop the job running on the cloud.
16:02:40 UTC starting up solver
running solver
early shutoff detected at 8%, exiting.
status = queued
16:02:52 UTC status = running
16:02:54 UTC status = postprocess
16:02:56 UTC status = success
16:02:58 UTC View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-4324d3d1-499 a-4ce0-a79a-d44a1aa46cd7'.
Loading results from data/data_dipole.hdf5
After the job is done, all of the data is loaded into the SimulationData object called sim_data in this example.
From this, we can plot the results and make sure it looks reasonable.
# check that frequency domain fields look good
ax = sim_data.plot_field("freq_domain", "Ez", y=0, f=freq0)
plt.show()To make things more interesting, let’s run the same simulation, but adding a few structures in the mix. For now, let’s just add a few dielectric box objects to see how that changes the results.
# define the boxes
epsilon_box = 3
center_offset_box = 1.6
size_box = 1.8
medium = td.Medium(permittivity=epsilon_box, name="medium")
box_top = td.Structure(
geometry=td.Box(
center=(0, 0, center_offset_box),
size=(size_box, size_box, size_box),
),
medium=medium,
name="box top",
)
bot_bot_r = td.Structure(
geometry=td.Box(
center=(+center_offset_box, 0, -center_offset_box),
size=(size_box, size_box, size_box),
),
medium=medium,
name="box bottom right",
)
bot_bot_l = td.Structure(
geometry=td.Box(
center=(-center_offset_box, 0, -center_offset_box),
size=(size_box, size_box, size_box),
),
medium=medium,
name="box bottom left",
)# make a new simulation with the boxes added
simulation_boxes = td.Simulation(
size=(side_length, side_length, side_length),
grid_spec=td.GridSpec.uniform(dl=grid_size),
structures=[box_top, bot_bot_r, bot_bot_l],
sources=[dipole_source],
monitors=[monitor],
run_time=run_time,
boundary_spec=boundary_spec,
)
# visualize the simulation first, before running
ax = simulation_boxes.plot(y=0.01)
plt.show()# run simulation
sim_data_boxes = web.run(
simulation_boxes,
task_name="lecture01_several_box",
path="data/data_several_box.hdf5",
)16:02:59 UTC Created task 'lecture01_several_box' with resource_id 'fdve-fc1a6242-6dd5-4222-b78d-6cbd435be18f' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-fc1a6242-6dd 5-4222-b78d-6cbd435be18f'.
Task folder: 'default'.
Estimated FlexCredit cost: 0.025. This assumes the FDTD solver runs for the full simulation time; if early shutoff is reached, the billed cost can be lower. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
status = queued
To cancel the simulation, use 'web.abort(task_id)' or 'web.delete(task_id)' or abort/delete the task in the web UI. Terminating the Python script will not stop the job running on the cloud.
16:03:11 UTC starting up solver
running solver
16:03:15 UTC early shutoff detected at 68%, exiting.
status = postprocess
16:03:17 UTC status = success
16:03:19 UTC View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-fc1a6242-6dd 5-4222-b78d-6cbd435be18f'.
Loading results from data/data_several_box.hdf5
ax = sim_data_boxes.plot_field("freq_domain", "Ez", y=0, f=freq0)
plt.show()