Skip to content

Commit

Permalink
mode sources and monitors work with conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
twhughes authored and tylerflex committed Oct 21, 2021
1 parent d076eb5 commit 7cec00c
Show file tree
Hide file tree
Showing 11 changed files with 445 additions and 672 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,6 @@ https://www.atlassian.com/git/tutorials/merging-vs-rebasing
- [x] Simplify MonitorData
- [x] remove MonitorData.monitor and MonitorData.monitor_name attributes.
- [x] remove MonitorData.load() and MonitorData.export()
- [ ] assert all SimulationData.monitor_data.keys() are in SimulationData.simulation.monitor.keys() <- not necessry.
- [ ] provide optional args to SimulationData.export() to only export some MonitorData by key <- not necessary?
- [ ] Move any interfaces in MonitorData to SimulationData (geometry, plotting, etc).
- [x] Make monitordata.load_from_group aware of lists
- [x] Use shapely for geometry ops / plotting? `Geometry.geo(x=0)` -> shapely representation.
- [x] Fix all tests.
Expand All @@ -208,12 +205,13 @@ https://www.atlassian.com/git/tutorials/merging-vs-rebasing
- [ ] Handle Inf as it's own keyword that depends on simulation bounds.
- [ ] Make Uniform Samplers separate classes? (dont evaluate / store freqs, times)?
- [ ] setup.cfg for installing packages with more granularity (base, docs, tests)
- [ ] Move any interfaces in MonitorData to SimulationData (geometry, plotting, etc).


#### Requires some focused time
- [ ] Nail down simulationData interfaces for plotting.
- [ ] Figue out webAPI running progress issues. (can we get separate status for time-stepping?)
- [ ] **Conversion for mode monitors / mode sources.**
- [x] Conversion for mode monitors / mode sources.
- [ ] Get near2far working correctly.
- [ ] Use mode solver for the relevant example notebooks.
- [ ] Document everything fully.
Expand Down
973 changes: 373 additions & 600 deletions notebooks/Modal_sources_monitors.ipynb

Large diffs are not rendered by default.

Binary file added notebooks/data/mode_converter.hdf5
Binary file not shown.
Binary file modified notebooks/data/simulation.hdf5
Binary file not shown.
Binary file modified notebooks/data/simulation_data.hdf5
Binary file not shown.
Binary file removed notebooks/simulation_data.hdf5
Binary file not shown.
Binary file removed simulation_data.hdf5
Binary file not shown.
6 changes: 3 additions & 3 deletions tidy3d/components/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ def load_from_group(cls, hdf5_grp):
kwargs[data_name] = np.array(data_value)

# handle data stored as np.array() of bytes instead of strings
# for str_kwarg in ("field", "direction"):
# if kwargs.get(str_kwarg) is not None:
# kwargs[str_kwarg] = decode_bytes_array(kwargs[str_kwarg])
for str_kwarg in ("direction",):
if kwargs.get(str_kwarg) is not None:
kwargs[str_kwarg] = decode_bytes_array(kwargs[str_kwarg])

# handle data stored as np.array() of bytes instead of strings
# for str_kwarg in ("x", "y", "z"):
Expand Down
1 change: 0 additions & 1 deletion tidy3d/components/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from .base import Tidy3dBaseModel
from .types import Symmetry
from ..log import log


class Mode(Tidy3dBaseModel):
Expand Down
9 changes: 7 additions & 2 deletions tidy3d/web/webapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,10 @@ def download(task_id: TaskId, simulation: Simulation, path: str = "simulation_da


def load_data(
task_id: TaskId, simulation: Simulation, path: str = "simulation_data.hdf5"
task_id: TaskId,
simulation: Simulation,
path: str = "simulation_data.hdf5",
replace_existing=True,
) -> SimulationData:
"""Download and Load simultion results into ``SimulationData`` object.
Expand All @@ -263,13 +266,15 @@ def load_data(
Unique identifier of task on server.
path : ``str``
Download path to .hdf5 data file (including filename).
replace_existing: ``bool``
Downloads even if file exists (overwriting).
Returns
-------
:class:`SimulationData`
Object containing simulation data.
"""
if not os.path.exists(path):
if not os.path.exists(path) or replace_existing:
download(task_id=task_id, simulation=simulation, path=path)

log.info(f"loading SimulationData from {path}")
Expand Down
122 changes: 60 additions & 62 deletions tidy3d_core/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from tidy3d import VolumeSource, ModeSource, PlaneWave
from tidy3d import GaussianPulse
from tidy3d import FieldMonitor, FieldTimeMonitor, FluxMonitor, FluxTimeMonitor
from tidy3d.components.monitor import AbstractFieldMonitor, AbstractFluxMonitor
from tidy3d.components.monitor import AbstractFieldMonitor, AbstractFluxMonitor, ModeMonitor
from tidy3d.components.monitor import FreqMonitor, TimeMonitor
from .solver import SolverDataDict

Expand Down Expand Up @@ -241,18 +241,6 @@ def old_json_sources(sim: Simulation) -> List[Dict]:
if src:
src_list.append(src)

# """ TODO: Support PointDipole as a subclass of VolumeSource """
# elif isinstance(source, PointDipole):
# src = {
# "name": src_data.name,
# "type": "PointDipole",
# "source_time": src_time,
# "center": source.center.tolist(),
# "size": source.size.tolist(),
# "component": source.component,
# "amplitude": float(source.amplitude),
# }
# """ TODO: Support PlaneWave """
# """ TODO: Support GaussianBeam """
# elif isinstance(source, GaussianBeam):
# src = {
Expand Down Expand Up @@ -303,65 +291,63 @@ def old_json_monitors(sim: Simulation) -> Dict:
For that, and more generally, it seems that currently the Simulation doesn't have a
TimeGrid or somethng like it? This is also needed e.g. to plot the source dependence, etc.
"""
if isinstance(monitor, FieldTimeMonitor):
store = []
if np.any([field[0] == "E" for field in monitor.fields]):
store.append("E")
if np.any([field[0] == "H" for field in monitor.fields]):
store.append("H")
mnt.update(
{
"type": "TimeMonitor",
"t_start": 0,
"t_stop": sim.run_time,
"t_step": None,
"store": store,
}
)
elif isinstance(monitor, FluxTimeMonitor):
mnt.update(
{
"type": "TimeMonitor",
"t_start": 0,
"t_stop": sim.run_time,
"t_step": None,
"store": ["flux"],
}
)
elif isinstance(monitor, FieldMonitor):
if isinstance(monitor, AbstractFieldMonitor):
store = []
if np.any([field[0] == "E" for field in monitor.fields]):
store.append("E")
if np.any([field[0] == "H" for field in monitor.fields]):
store.append("H")
if isinstance(monitor, FieldMonitor):
mnt.update(
{
"type": "FrequencyMonitor",
"frequency": [f * 1e-12 for f in monitor.freqs],
"store": store,
"interpolate": True,
}
)
elif isinstance(monitor, FieldTimeMonitor):
mnt.update(
{
"type": "TimeMonitor",
"t_start": 0,
"t_stop": sim.run_time,
"t_step": None,
"store": store,
}
)
elif isinstance(monitor, AbstractFluxMonitor):
if isinstance(monitor, FluxTimeMonitor):
mnt.update(
{
"type": "TimeMonitor",
"t_start": 0,
"t_stop": sim.run_time,
"t_step": None,
"store": ["flux"],
}
)
elif isinstance(monitor, FluxMonitor):
mnt.update(
{
"type": "FrequencyMonitor",
"frequency": [f * 1e-12 for f in monitor.freqs],
"store": ["flux"],
"interpolate": True,
}
)
elif isinstance(monitor, ModeMonitor):
num_modes = max([m.mode_index for m in monitor.modes]) + 1
mnt.update(
{
"type": "FrequencyMonitor",
"frequency": [f * 1e-12 for f in monitor.freqs],
"store": store,
"interpolate": True,
}
)
elif isinstance(monitor, FluxMonitor):
mnt.update(
{
"type": "FrequencyMonitor",
"type": "ModeMonitor",
"frequency": [f * 1e-12 for f in monitor.freqs],
"store": ["flux"],
"interpolate": True,
"Nmodes": num_modes,
"target_neff": None,
"store": ["mode_amps"],
}
)
""" TODO: support ModeMonitor """
# elif isinstance(monitor, ModeMonitor):
# mnt.update(
# {
# "type": "ModeMonitor",
# "frequency": [f * 1e-12 for f in monitor.freqs],
# "Nmodes": mnt_data.Nmodes,
# "target_neff": mnt_data.target_neff,
# }
# )
#

""" TODO: Support PermittivityMonitor """
#

Expand Down Expand Up @@ -439,8 +425,20 @@ def load_old_monitor_data(simulation: Simulation, data_file: str) -> SolverDataD
"values": field_vals,
sampler_label: sampler_values,
}

elif isinstance(monitor, AbstractFluxMonitor):
values = np.array(f_handle[name]["flux"]).ravel()
data_dict[name] = {"values": values, sampler_label: sampler_values}

elif isinstance(monitor, ModeMonitor):
values = np.array(f_handle[name]["mode_amps"])
values = np.swapaxes(values, 1, 2) # put frequency at last axis
mode_index = np.arange(values.shape[1])
data_dict[name] = {
"values": values,
"direction": ["+", "-"],
"mode_index": mode_index,
sampler_label: sampler_values,
}

return data_dict

0 comments on commit 7cec00c

Please sign in to comment.