Skip to content

Commit d1d5995

Browse files
docstrings
1 parent dcc5995 commit d1d5995

File tree

6 files changed

+175
-135
lines changed

6 files changed

+175
-135
lines changed

tidy3d/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@
125125
HeatDataArray,
126126
IndexedDataArray,
127127
IndexedVoltageDataArray,
128+
IndexedFieldDataArray,
129+
IndexedFieldTimeDataArray,
130+
IndexedFreqDataArray,
131+
IndexedTimeDataArray,
128132
ModeAmpsDataArray,
129133
ModeIndexDataArray,
130134
PointDataArray,
@@ -622,6 +626,10 @@ def set_logging_level(level: str) -> None:
622626
"CellDataArray",
623627
"IndexedDataArray",
624628
"IndexedVoltageDataArray",
629+
"IndexedFieldDataArray",
630+
"IndexedFieldTimeDataArray",
631+
"IndexedFreqDataArray",
632+
"IndexedTimeDataArray",
625633
"SteadyVoltageDataArray",
626634
"TriangularGridDataset",
627635
"TetrahedralGridDataset",

tidy3d/components/data/data_array.py

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,23 +1253,8 @@ class SpatialVoltageDataArray(AbstractSpatialDataArray):
12531253
_dims = ("x", "y", "z", "voltage")
12541254

12551255

1256-
class IndexedVectorDataArray(DataArray):
1257-
"""Stores a mutlidimensional array enumerated by coordinates ``index`` and ``axis``. It is typically used
1258-
in conjuction with a ``PointDataArray`` to store point-associated vector data.
1259-
1260-
Example
1261-
-------
1262-
>>> indexed_array = IndexedFieldDataArray(
1263-
... (1+1j) * np.random.random((4,3)), coords=dict(index=np.arange(4), axis=np.arange(3))
1264-
... )
1265-
"""
1266-
1267-
__slots__ = ()
1268-
_dims = ("index", "axis")
1269-
1270-
12711256
class IndexedFieldDataArray(DataArray):
1272-
"""Stores a mutlidimensional array enumerated by coordinates ``index`` and ``axis``. It is typically used
1257+
"""Stores indexed values of vector fields in frequency domain. It is typically used
12731258
in conjuction with a ``PointDataArray`` to store point-associated vector data.
12741259
12751260
Example
@@ -1284,7 +1269,7 @@ class IndexedFieldDataArray(DataArray):
12841269

12851270

12861271
class IndexedFieldTimeDataArray(DataArray):
1287-
"""Stores a mutlidimensional array enumerated by coordinates ``index`` and ``axis``. It is typically used
1272+
"""Stores indexed values of vector fields in time domain. It is typically used
12881273
in conjuction with a ``PointDataArray`` to store point-associated vector data.
12891274
12901275
Example
@@ -1299,13 +1284,13 @@ class IndexedFieldTimeDataArray(DataArray):
12991284

13001285

13011286
class IndexedFreqDataArray(DataArray):
1302-
"""Stores a mutlidimensional array enumerated by coordinates ``index`` and ``axis``. It is typically used
1287+
"""Stores indexed values of scalar fields in frequency domain. It is typically used
13031288
in conjuction with a ``PointDataArray`` to store point-associated vector data.
13041289
13051290
Example
13061291
-------
13071292
>>> indexed_array = IndexedFieldDataArray(
1308-
... (1+1j) * np.random.random((4,3,1)), coords=dict(index=np.arange(4), axis=np.arange(3), f=[1e9])
1293+
... (1+1j) * np.random.random((4,1)), coords=dict(index=np.arange(4), f=[1e9])
13091294
... )
13101295
"""
13111296

@@ -1314,13 +1299,13 @@ class IndexedFreqDataArray(DataArray):
13141299

13151300

13161301
class IndexedTimeDataArray(DataArray):
1317-
"""Stores a mutlidimensional array enumerated by coordinates ``index`` and ``axis``. It is typically used
1302+
"""Stores indexed values of scalar fields in time domain. It is typically used
13181303
in conjuction with a ``PointDataArray`` to store point-associated vector data.
13191304
13201305
Example
13211306
-------
13221307
>>> indexed_array = IndexedFieldDataArray(
1323-
... (1+1j) * np.random.random((4,3,1)), coords=dict(index=np.arange(4), axis=np.arange(3), t=[0])
1308+
... (1+1j) * np.random.random((4,1)), coords=dict(index=np.arange(4), t=[0])
13241309
... )
13251310
"""
13261311

@@ -1361,7 +1346,6 @@ class IndexedTimeDataArray(DataArray):
13611346
CellDataArray,
13621347
IndexedDataArray,
13631348
IndexedVoltageDataArray,
1364-
IndexedVectorDataArray,
13651349
IndexedFieldDataArray,
13661350
IndexedFieldTimeDataArray,
13671351
IndexedFreqDataArray,
@@ -1372,9 +1356,9 @@ class IndexedTimeDataArray(DataArray):
13721356
IndexedDataArrayTypes = Union[
13731357
IndexedDataArray,
13741358
IndexedVoltageDataArray,
1375-
IndexedVectorDataArray,
13761359
IndexedFieldDataArray,
13771360
IndexedFieldTimeDataArray,
13781361
IndexedFreqDataArray,
13791362
IndexedTimeDataArray,
1363+
PointDataArray,
13801364
]

tidy3d/components/data/dataset.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ def apply_phase(self, phase: float) -> AbstractFieldDataset:
314314

315315

316316
class ElectromagneticSurfaceFieldDataset(AbstractFieldDataset, ABC):
317-
"""Stores a collection of E, H and J fields with x, y, z components. The E is normal to the surface while H and J fields are tangential."""
317+
"""Stores a collection of E and H fields with x, y, z components."""
318318

319319
E: Tuple[Optional[TriangularSurfaceDataset], Optional[TriangularSurfaceDataset]] = pd.Field(
320320
(None, None),
@@ -360,7 +360,7 @@ def current_density(self) -> ElectromagneticSurfaceFieldDataset:
360360
if template is None:
361361
raise ValueError("Could not calculate current density: the dataset does not contain H field information.")
362362

363-
return template.updated_copy(np.cross(h_diff, self.normal.values, dim="axis"))
363+
return template.updated_copy(xr.cross(h_diff, self.normal.values, dim="axis"))
364364

365365
@property
366366
def grid_locations(self) -> Dict[str, str]:

tidy3d/components/data/monitor_data.py

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,6 @@
9494
ModeSolverDataset,
9595
PermittivityDataset,
9696
ElectromagneticSurfaceFieldDataset,
97-
# SurfaceFieldDataset,
98-
# SurfaceFieldTimeDataset,
9997
)
10098
from .utils import TriangularSurfaceDataset
10199

@@ -1335,7 +1333,7 @@ def time_reversed_copy(self) -> FieldTimeData:
13351333

13361334

13371335
class AbstractSurfaceFieldData(MonitorData, AbstractFieldDataset, ABC):
1338-
"""Collection of scalar fields with some symmetry properties."""
1336+
"""Collection of vector fields on a surfacewith some symmetry properties."""
13391337

13401338
monitor: Union[SurfaceFieldMonitor, SurfaceFieldTimeMonitor]
13411339

@@ -1356,14 +1354,14 @@ class AbstractSurfaceFieldData(MonitorData, AbstractFieldDataset, ABC):
13561354

13571355
@property
13581356
def symmetry_expanded(self):
1359-
"""Return the :class:`.AbstractFieldData` with fields expanded based on symmetry. If
1357+
"""Return the :class:`.AbstractSurfaceFieldData` with fields expanded based on symmetry. If
13601358
any symmetry is nonzero (i.e. expanded), the interpolation implicitly creates a copy of the
13611359
data array. However, if symmetry is not expanded, the returned array contains a view of
13621360
the data, not a copy.
13631361
13641362
Returns
13651363
-------
1366-
:class:`AbstractFieldData`
1364+
:class:`AbstractSurfaceFieldData`
13671365
A data object with the symmetry expanded fields.
13681366
"""
13691367

@@ -1374,11 +1372,11 @@ def symmetry_expanded(self):
13741372

13751373
@property
13761374
def symmetry_expanded_copy(self) -> AbstractFieldData:
1377-
"""Create a copy of the :class:`.AbstractFieldData` with fields expanded based on symmetry.
1375+
"""Create a copy of the :class:`.AbstractSurfaceFieldData` with fields expanded based on symmetry.
13781376
13791377
Returns
13801378
-------
1381-
:class:`AbstractFieldData`
1379+
:class:`AbstractSurfaceFieldData`
13821380
A data object with the symmetry expanded fields.
13831381
"""
13841382

@@ -1395,7 +1393,7 @@ def _symmetry_update_dict(self) -> Dict:
13951393

13961394

13971395
class ElectromagneticSurfaceFieldData(AbstractSurfaceFieldData, ElectromagneticSurfaceFieldDataset, ABC):
1398-
"""Collection of electromagnetic fields."""
1396+
"""Collection of electromagnetic fields on a surface."""
13991397

14001398
@property
14011399
def intensity(self) -> Tuple[TriangularSurfaceDataset, TriangularSurfaceDataset]:
@@ -1404,12 +1402,12 @@ def intensity(self) -> Tuple[TriangularSurfaceDataset, TriangularSurfaceDataset]
14041402
for ind in range(2):
14051403
if self.E[ind] is not None:
14061404
e_field = self.E[ind]
1407-
intensity[ind] = e_field.updated_copy(values=sum(e_field.values.sel(axis=axis) ** 2 for axis in range(3)))
1405+
intensity[ind] = e_field.norm(dim="axis") ** 2
14081406
return intensity
14091407

14101408
@property
14111409
def poynting(self) -> Tuple[TriangularSurfaceDataset, TriangularSurfaceDataset]:
1412-
"""Time-averaged Poynting vector for frequency-domain data associated to a surface monitor."""
1410+
"""Time-averaged Poynting vector for frequency-domain data."""
14131411

14141412
poynting = [None, None]
14151413
for ind in range(2):
@@ -1436,22 +1434,21 @@ def _check_fields_stored(self, components: list[str]):
14361434

14371435
class SurfaceFieldData(ElectromagneticSurfaceFieldData):
14381436
"""
1439-
Data associated with a :class:`.SurfaceFieldMonitor`: scalar components of E and H fields.
1437+
Data associated with a :class:`.SurfaceFieldMonitor`: E and H fields on a surface.
14401438
14411439
Example
14421440
-------
1443-
>>> from tidy3d import ScalarFieldDataArray
1444-
>>> x = [-1,1,3]
1445-
>>> y = [-2,0,2,4]
1446-
>>> z = [-3,-1,1,3,5]
1447-
>>> f = [2e14, 3e14]
1448-
>>> coords = dict(x=x[:-1], y=y[:-1], z=z[:-1], f=f)
1449-
>>> grid = Grid(boundaries=Coords(x=x, y=y, z=z))
1450-
>>> scalar_field = ScalarFieldDataArray((1+1j) * np.random.random((2,3,4,2)), coords=coords)
1451-
>>> monitor = FieldMonitor(
1452-
... size=(2,4,6), freqs=[2e14, 3e14], name='field', fields=['Ex', 'Hz'], colocate=True
1441+
>>> from tidy3d import PointDataArray, IndexedFieldDataArray, TriangularSurfaceDataset, CellDataArray
1442+
>>> points = PointDataArray([[0, 0, 0], [0, 1, 0], [1, 1, 1]], dims=["index", "axis"])
1443+
>>> cells = CellDataArray([[0, 1, 2]], dims=["cell_index", "vertex_index"])
1444+
>>> values = PointDataArray([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dims=["index", "axis"])
1445+
>>> field_values = IndexedFieldDataArray(np.ones((3, 3, 1)) + 0j, coords={"index": [0, 1, 2], "axis": [0, 1, 2], "f": [1e10]})
1446+
>>> field = TriangularSurfaceDataset(points=points, cells=cells, values=field_values)
1447+
>>> normal = TriangularSurfaceDataset(points=points, cells=cells, values=values)
1448+
>>> monitor = SurfaceFieldMonitor(
1449+
... size=(2,4,6), freqs=[1e10], name='field', fields=['E', 'H']
14531450
... )
1454-
>>> data = FieldData(monitor=monitor, Ex=scalar_field, Hz=scalar_field, grid_expanded=grid)
1451+
>>> data = SurfaceFieldData(monitor=monitor, E=[None, field], H=[None, field], normal=normal)
14551452
14561453
"""
14571454

@@ -1463,11 +1460,14 @@ class SurfaceFieldData(ElectromagneticSurfaceFieldData):
14631460

14641461
def normalize(self, source_spectrum_fn: Callable[[float], complex]) -> FieldDataset:
14651462
"""Return copy of self after normalization is applied using source spectrum function."""
1466-
return self
14671463
fields_norm = {}
14681464
for field_name, field_data in self.field_components.items():
1469-
src_amps = source_spectrum_fn(field_data.f)
1470-
fields_norm[field_name] = (field_data / src_amps).astype(field_data.dtype)
1465+
fields_norm[field_name] = [None, None]
1466+
for ind in range(2):
1467+
src_amps = source_spectrum_fn(field_data[ind].values.f)
1468+
fields_norm[field_name][ind] = field_data[ind].updated_copy(
1469+
values=(field_data[ind].values / src_amps).astype(field_data[ind].values.dtype)
1470+
)
14711471

14721472
return self.copy(update=fields_norm)
14731473

@@ -1477,18 +1477,17 @@ class SurfaceFieldTimeData(ElectromagneticSurfaceFieldData):
14771477
14781478
Example
14791479
-------
1480-
>>> from tidy3d import ScalarFieldTimeDataArray
1481-
>>> x = [-1,1,3]
1482-
>>> y = [-2,0,2,4]
1483-
>>> z = [-3,-1,1,3,5]
1484-
>>> t = [0, 1e-12, 2e-12]
1485-
>>> coords = dict(x=x[:-1], y=y[:-1], z=z[:-1], t=t)
1486-
>>> grid = Grid(boundaries=Coords(x=x, y=y, z=z))
1487-
>>> scalar_field = ScalarFieldTimeDataArray(np.random.random((2,3,4,3)), coords=coords)
1488-
>>> monitor = FieldTimeMonitor(
1489-
... size=(2,4,6), interval=100, name='field', fields=['Ex', 'Hz'], colocate=True
1480+
>>> from tidy3d import PointDataArray, IndexedFieldDataArray, TriangularSurfaceDataset, CellDataArray
1481+
>>> points = PointDataArray([[0, 0, 0], [0, 1, 0], [1, 1, 1]], dims=["index", "axis"])
1482+
>>> cells = CellDataArray([[0, 1, 2]], dims=["cell_index", "vertex_index"])
1483+
>>> values = PointDataArray([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dims=["index", "axis"])
1484+
>>> field_values = IndexedFieldDataArray(np.ones((3, 3, 1)) + 0j, coords={"index": [0, 1, 2], "axis": [0, 1, 2], "f": [1e10]})
1485+
>>> field = TriangularSurfaceDataset(points=points, cells=cells, values=field_values)
1486+
>>> normal = TriangularSurfaceDataset(points=points, cells=cells, values=values)
1487+
>>> monitor = SurfaceFieldTimeMonitor(
1488+
... size=(2,4,6), interval=100, name='field', fields=['E', 'H']
14901489
... )
1491-
>>> data = FieldTimeData(monitor=monitor, Ex=scalar_field, Hz=scalar_field, grid_expanded=grid)
1490+
>>> data = SurfaceFieldTimeData(monitor=monitor, E=[None, field], H=[None, field], normal=normal)
14921491
"""
14931492

14941493
monitor: SurfaceFieldTimeMonitor = pd.Field(
@@ -1499,16 +1498,20 @@ class SurfaceFieldTimeData(ElectromagneticSurfaceFieldData):
14991498

15001499
@property
15011500
def poynting(self) -> ScalarFieldTimeDataArray:
1502-
"""Instantaneous Poynting vector for time-domain data associated to a 2D monitor, projected
1503-
to the direction normal to the monitor plane."""
1501+
"""Instantaneous Poynting vector for time-domain data."""
15041502

1505-
# TODO: fix this
1506-
# # Tangential fields are ordered as E1, E2, H1, H2
1507-
# tan_fields = self._colocated_tangential_fields
1508-
# dim1, dim2 = self._tangential_dims
1509-
# e_x_h = np.real(tan_fields["E" + dim1]) * np.real(tan_fields["H" + dim2])
1510-
# e_x_h -= np.real(tan_fields["E" + dim2]) * np.real(tan_fields["H" + dim1])
1511-
# return e_x_h
1503+
poynting = [None, None]
1504+
for ind in range(2):
1505+
if self.E[ind] is not None and self.H[ind] is not None:
1506+
1507+
e_field = self.E[ind]
1508+
h_field = self.H[ind]
1509+
1510+
poynting[ind] = e_field.updated_copy(
1511+
values=np.real(xr.cross(e_field.values.real, h_field.values.real, dim="axis"))
1512+
)
1513+
1514+
return poynting
15121515

15131516

15141517
class PermittivityData(PermittivityDataset, AbstractFieldData):

0 commit comments

Comments
 (0)