9494 ModeSolverDataset ,
9595 PermittivityDataset ,
9696 ElectromagneticSurfaceFieldDataset ,
97- # SurfaceFieldDataset,
98- # SurfaceFieldTimeDataset,
9997)
10098from .utils import TriangularSurfaceDataset
10199
@@ -1335,7 +1333,7 @@ def time_reversed_copy(self) -> FieldTimeData:
13351333
13361334
13371335class 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
13971395class 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
14371435class 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
15141517class PermittivityData (PermittivityDataset , AbstractFieldData ):
0 commit comments