Closed chenyudong92 closed 1 year ago
Hi @chenyudong92 what version of tidy3d are you using? If you do
import tidy3d
in a python shell, what version number gets displayed?
With the most recent release (1.8.3) I am able to import FieldProjectionAngleMonitor
To upgrade to version 1.8.3, you can do
pip install --upgrade tidy3d
when I upgrade, the issue solved. Thanks for your help!
Sincerely, Yudong Chen M.S. of Electrical Engineering at SMU Ph.D. Student of Electrical Engineering at UTA Office at 2nd floor of NanoFab at UTA
发件人: Tyler Hughes @.> 发送时间: Thursday, February 2, 2023 7:32:28 PM 收件人: flexcompute/tidy3d @.> 抄送: Chen, Yudong @.>; Mention @.> 主题: Re: [flexcompute/tidy3d] Issue on page /_autosummary/tidy3d.FieldProjectionAngleMonitor.html (Issue #677)
[External]
Hi @chenyudong92https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fchenyudong92&data=05%7C01%7Cyudong.chen%40mavs.uta.edu%7Cf86a7d612a8b4ed2a7da08db058682e0%7C5cdc5b43d7be4caa8173729e3b0a62d9%7C0%7C0%7C638109847502560143%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=3zYtGSJQ8rBtr22%2BR0HKcf03Yy2WhjNRNMXQGVZZWe8%3D&reserved=0 what version of tidy3d are you using? If you do
import tidy3d
in a python shell, what version number gets displayed? With the most recent release (1.8.3) I am able to import FieldProjectionAngleMonitor [image]https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fuser-images.githubusercontent.com%2F92756888%2F216489677-7461052b-86a6-40de-9d08-7e26c0c771f5.png&data=05%7C01%7Cyudong.chen%40mavs.uta.edu%7Cf86a7d612a8b4ed2a7da08db058682e0%7C5cdc5b43d7be4caa8173729e3b0a62d9%7C0%7C0%7C638109847502560143%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=RBfX5IchWnFDzx9MvzkLwGlVPz6%2Bw4rQVGELm0uooZg%3D&reserved=0
To upgrade to version 1.8.3, you can do
pip install --upgrade tidy3d
― Reply to this email directly, view it on GitHubhttps://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fflexcompute%2Ftidy3d%2Fissues%2F677%23issuecomment-1414590806&data=05%7C01%7Cyudong.chen%40mavs.uta.edu%7Cf86a7d612a8b4ed2a7da08db058682e0%7C5cdc5b43d7be4caa8173729e3b0a62d9%7C0%7C0%7C638109847502560143%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=omElU7j6DVbg7zU4RxUB30PdXxIH43qH575HnEIYCuw%3D&reserved=0, or unsubscribehttps://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FANXYTVZZ3HMF54TA77DCUKTWVRN2ZANCNFSM6AAAAAAUPVS424&data=05%7C01%7Cyudong.chen%40mavs.uta.edu%7Cf86a7d612a8b4ed2a7da08db058682e0%7C5cdc5b43d7be4caa8173729e3b0a62d9%7C0%7C0%7C638109847502560143%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=iRETwRVeDm9pNBCAIDg1QQkFyIBpt1hlEQ8nqYfrLhE%3D&reserved=0. You are receiving this because you were mentioned.Message ID: @.***>
great!
When I try to use function: tidy3d.FieldProjectionAngleMonitor for far field distribution.
It shows: AttributeError: module 'tidy3d' has no attribute 'FieldProjectionAngleMonitor'.
Could you help me figure it out?
below is all my code:
%%
standard python imports
import numpy as np import matplotlib.pyplot as plt
tidy3d imports
import tidy3d as td import tidy3d.web as web
%%
radius and location of the sphere
radius = 10 center = [0, 0, 0]
permittivity of the sphere
epsr = 4
free space central wavelength
wavelength = (2.0 * radius) / 2.0
wavelength = 0.94 f0 = td.C_0 / wavelength
distance between the surface of the sphere and the start of the PML layers along each cartesian direction
buffer_PML = 3 * wavelength
distance between the sphere and the near field monitor along each cartesian direction
buffer_mon = 1 * wavelength
Define material properties
air = td.Medium(permittivity=1) diel = td.Medium(permittivity=epsr)
resolution control
min_steps_per_wvl = 24
create the sphere
sphere = td.Structure(geometry=td.Sphere(center=center, radius=radius), medium=diel) geometry = []
define PML layers on all sides
boundary_spec = td.BoundarySpec.all_sides(boundary=td.PML())
set the domain size in x, y, and z
domain_size = buffer_PML + 2 * radius + buffer_PML
construct simulation size array
sim_size = (domain_size, domain_size, domain_size)
Bandwidth in Hz
fwidth = f0 / 10.0
Gaussian source offset; the source peak is at time t = offset/fwidth
offset = 4.0
time dependence of source
gaussian = td.GaussianPulse(freq0=f0, fwidth=fwidth, offset=offset)
place the source below the sphere, propagating in the +z direction
source = td.PlaneWave(
center=(0, 0, -(radius + 3 * buffer_PML / 4)),
size=(td.inf, td.inf, 0),
source_time=gaussian,
direction="+",
pol_angle=0,
)
source = td.GaussianBeam( source_time=gaussian, direction='+', size=(td.inf, td.inf, 0), center=(0, 0, -(radius + 3 * buffer_PML / 4)),
pol_angle=0.0, ##### 0 for p-lolarization, np.pi/2 specifies S-polarization
Simulation run time past the source decay (around t=2*offset/fwidth)
run_time = 100 / fwidth
create a set of surface monitors around the sphere for local computation of far fields
mon_size = 2 radius + 2 buffer_mon monitors_near = td.FieldMonitor.surfaces( center=center, size=[mon_size, mon_size, mon_size], freqs=[f0], name="near_field" )
set the far-field observation angles of interest
num_theta = 300 num_phi = 2 thetas = np.linspace(0, np.pi, num_theta) phis = np.linspace(0, np.pi / 2, num_phi)
create the far field monitor for server-side computation of far fields
monitor_far = td.FieldProjectionAngleMonitor( center=center, size=[mon_size, mon_size, mon_size], freqs=[f0], name="far_field", custom_origin=center, phi=list(phis), theta=list(thetas), far_field_approx=True, # we leave this to its default value of 'True' because we are interested in fields sufficiently
far away that the far field approximations can be invoked to speed up the calculation
)
create a set of surface monitors around the sphere
monitors_downsampled = td.FieldMonitor.surfaces( center=center, size=[mon_size, mon_size, mon_size], freqs=[f0], name="near_field_downsampled", interval_space=( 2, 2, 3, ), # these are the (x, y, z) factors by which fields are downsampled ) monitors = monitors_near + [monitor_far] + monitors_downsampled
sim = td.Simulation( size=sim_size, grid_spec=td.GridSpec.auto(min_steps_per_wvl=min_steps_per_wvl), structures=geometry, sources=[source], monitors=monitors, run_time=run_time, boundary_spec=boundary_spec, symmetry=(-1, 1, 0), )
Here, we add the sphere as an override structure for the messhing such
that the grids of the two simulations match.
sim_empty = td.Simulation( size=sim_size, grid_spec=td.GridSpec.auto( min_steps_per_wvl=min_steps_per_wvl, override_structures=geometry, ), structures=[], sources=[source], monitors=monitors, run_time=run_time, boundary_spec=boundary_spec, symmetry=(-1, 1, 0), ) fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 3)) sim.plot(y=0, ax=ax1) sim_empty.plot(y=0, ax=ax2)
Run simulation
import tidy3d.web as web
sim_data = web.run(sim, task_name="sphereRCS", path="data/sphereRCS.hdf5") sim_empty_data = web.run( sim_empty, task_name="sphereRCS_empty", path="data/sphereRCS_empty.hdf5" ) import time
first, we construct the classes which compute far fields locally on your machine
n2f = td.FieldProjector.from_near_field_monitors( sim_data=sim_data, near_monitors=monitors_near, # only supply the non-downsampled surface monitors as sources normal_dirs=["-", "+", "-", "+", "-", "+"], pts_per_wavelength=10, )
do the same for the downsampled monitors
n2f_downsampled = td.FieldProjector.from_near_field_monitors( sim_data=sim_data, near_monitors=monitors_downsampled, # only supply the downsampled surface monitors as sources normal_dirs=["-", "+", "-", "+", "-", "+"], pts_per_wavelength=10, )
we'll also project the fields from the empty simulation into the far field to get the scattered far field
n2f_empty = td.FieldProjector.from_near_field_monitors( sim_data=sim_empty_data, near_monitors=monitors_near, # only supply the non-downsampled surface monitors as sources normal_dirs=["-", "+", "-", "+", "-", "+"], pts_per_wavelength=10, )
now, we retrieve the far fields in all three cases by passing in our far field monitor from before
start = time.time() far_fields = n2f.project_fields(monitor_far) end = time.time() n2f_time = end - start
start = time.time() far_fields_downsampled = n2f_downsampled.project_fields(monitor_far) end = time.time() n2f_downsampled_time = end - start
start = time.time() far_fields_empty = n2f_empty.project_fields(monitor_far) end = time.time() n2f_empty_time = end - start
use the simulation log to find the time taken for server-side computations
n2f_server_time = float( sim_data.log.split("Field projection time (s): ", 1)[1].split("\n", 1)[0] )
print(f"Local near-to-far: {n2f_time} s") print(f"Local near-to-far with downsampling: {n2f_downsampled_time} s") print(f"Server-side near-to-far: {n2f_server_time} s") far_fields_server = sim_data[monitor_far.name] far_fields_empty_server = sim_empty_data[monitor_far.name]
scattered fields for client-side projections
for field, field_empty in zip( far_fields.field_components.values(), far_fields_empty.field_components.values() ): field.values -= field_empty.values
scattered fields for server-side projections
for field, field_empty in zip( far_fields_server.field_components.values(), far_fields_empty_server.field_components.values(), ): field.values -= field_empty.values
get the RCS for the local, local downsampled and server-side cases
RCS = far_fields.radar_cross_section.sel(f=f0).values RCS_downsampled = far_fields_downsampled.radar_cross_section.sel(f=f0).values RCS_server = far_fields_server.radar_cross_section.sel(f=f0).values
def to_db(val): val = np.abs(val) / np.max(np.abs(val)) return 10.0 * np.log10(val)
RCS_phi0 = RCS[0, :, 0] RCS_phi90 = RCS[0, :, 1]
RCS_downsampled_phi0 = RCS_downsampled[0, :, 0] RCS_downsampled_phi90 = RCS_downsampled[0, :, 1]
RCS_server_phi0 = RCS_server[0, :, 0] RCS_server_phi90 = RCS_server[0, :, 1]
------ import analytical data from disk ------
mie_file_id = "2lambda_epsr4"
mie_filename_phi0 = "./data/mie_bRCSphi0" + mie_file_id + ".txt"
mie_filename_phi90 = "./data/mie_bRCSphi90" + mie_file_id + ".txt"
mie_data_phi0 = np.loadtxt(mie_filename_phi0, delimiter="\t", skiprows=2)
mie_theta_phi0 = np.squeeze(mie_data_phi0[:, [0]])
mie_phi0 = np.squeeze(mie_data_phi0[:, [1]])
mie_data_phi90 = np.loadtxt(mie_filename_phi90, delimiter="\t", skiprows=2)
mie_theta_phi90 = np.squeeze(mie_data_phi90[:, [0]])
mie_phi90 = np.squeeze(mie_data_phi90[:, [1]])
------ plot for phi = 0 ------
fig, ax = plt.subplots(figsize=(7.5, 5))
ax.plot(mie_theta_phi0, to_db(mie_phi0), "-k", label="$\phi = 0$, Mie")
ax.plot(thetas, to_db(RCS_phi0), "--b", label="$\phi = 0$, near2far local") ax.plot( thetas, to_db(RCS_downsampled_phi0), "--r", label="$\phi = 0$, near2far local downsampled", ) ax.plot(thetas, to_db(RCS_server_phi0), "--g", label="$\phi = 0$, near2far server") ax.set( xlabel="$\theta$ (degrees)", ylabel="Bistatic RCS (dBsm)", yscale="linear", xscale="linear", ) ax.grid(visible=True, which="both", axis="both", linewidth=0.4) plt.legend(loc="best", prop={"size": 14}) plt.tight_layout()
------ plot for phi = pi/2 ------
fig, ax = plt.subplots(figsize=(7.5, 5))
ax.plot(mie_theta_phi90, to_db(mie_phi90), "-k", label="$\phi = \pi/2$, Mie")
ax.plot(thetas, to_db(RCS_phi90), "--b", label="$\phi = \pi/2$, near2far local") ax.plot( thetas, to_db(RCS_downsampled_phi90), "--r", label="$\phi = \pi/2$, near2far local downsampled", ) ax.plot( thetas, to_db(RCS_server_phi90), "--g", label="$\phi = \pi/2$, near2far server" ) ax.set( xlabel="$\theta$ (degrees)", ylabel="Bistatic RCS (dBsm)", yscale="linear", xscale="linear", ) ax.grid(visible=True, which="both", axis="both", linewidth=0.4) plt.legend(loc="best", prop={"size": 14}) plt.tight_layout()
%%