Skip to content

Commit 6ecc0eb

Browse files
--amend
1 parent 8fcbe0b commit 6ecc0eb

File tree

1 file changed

+8
-100
lines changed

1 file changed

+8
-100
lines changed

tidy3d/plugins/smatrix/component_modelers/terminal.py

Lines changed: 8 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -446,102 +446,6 @@ def get_radiation_monitor_by_name(self, monitor_name: str) -> DirectivityMonitor
446446
return monitor
447447
raise Tidy3dKeyError(f"No radiation monitor named '{monitor_name}'.")
448448

449-
def get_antenna_metrics_data(
450-
self,
451-
port_amplitudes: Optional[dict[str, complex]] = None,
452-
monitor_name: Optional[str] = None,
453-
) -> AntennaMetricsData:
454-
"""Calculate antenna parameters using superposition of fields from multiple port excitations.
455-
456-
The method computes the radiated far fields and port excitation power wave amplitudes
457-
for a superposition of port excitations, which can be used to analyze antenna radiation
458-
characteristics.
459-
460-
Parameters
461-
----------
462-
port_amplitudes : dict[str, complex] = None
463-
Dictionary mapping port names to their desired excitation amplitudes, ``a``. For each port,
464-
:math:`\\frac{1}{2}|a|^2` represents the incident power from that port into the system.
465-
If ``None``, uses only the first port without any scaling of the raw simulation data.
466-
When ``None`` is passed as a port amplitude, the raw simulation data is used for that port.
467-
Note that in this method ``a`` represents the incident wave amplitude
468-
using the power wave definition in [2].
469-
monitor_name : str = None
470-
Name of the :class:`.DirectivityMonitor` to use for calculating far fields.
471-
If None, uses the first monitor in `radiation_monitors`.
472-
473-
Returns
474-
-------
475-
:class:`.AntennaMetricsData`
476-
Container with antenna parameters including directivity, gain, and radiation efficiency,
477-
computed from the superposition of fields from all excited ports.
478-
"""
479-
# Use the first port as default if none specified
480-
if port_amplitudes is None:
481-
port_amplitudes = {self.ports[0].name: None}
482-
483-
# Check port names, and create map from port to amplitude
484-
port_dict = {}
485-
for key in port_amplitudes.keys():
486-
port, _ = self.network_dict[key]
487-
port_dict[port] = port_amplitudes[key]
488-
# Get the radiation monitor, use first as default
489-
# if none specified
490-
if monitor_name is None:
491-
rad_mon = self.radiation_monitors[0]
492-
else:
493-
rad_mon = self.get_radiation_monitor_by_name(monitor_name)
494-
495-
# Create data arrays for holding the superposition of all port power wave amplitudes
496-
f = list(rad_mon.freqs)
497-
coords = {"f": f, "port": list(self.matrix_indices_monitor)}
498-
a_sum = PortDataArray(
499-
np.zeros((len(f), len(self.matrix_indices_monitor)), dtype=complex), coords=coords
500-
)
501-
b_sum = a_sum.copy()
502-
# Retrieve associated simulation data
503-
combined_directivity_data = None
504-
for port, amplitude in port_dict.items():
505-
if amplitude == 0.0:
506-
continue
507-
sim_data_port = self.batch_data[self._task_name(port=port)]
508-
radiation_data = sim_data_port[rad_mon.name]
509-
510-
a, b = self.compute_wave_amplitudes_at_each_port(
511-
self.port_reference_impedances, sim_data_port, s_param_def="power"
512-
)
513-
# Select a possible subset of frequencies
514-
a = a.sel(f=f)
515-
b = b.sel(f=f)
516-
a_raw = a.sel(port=self.network_index(port))
517-
518-
if amplitude is None:
519-
# No scaling performed when amplitude is None
520-
scaled_directivity_data = sim_data_port[rad_mon.name]
521-
scale_factor = 1.0
522-
else:
523-
scaled_directivity_data = self._monitor_data_at_port_amplitude(
524-
port, sim_data_port, radiation_data, amplitude
525-
)
526-
scale_factor = amplitude / a_raw
527-
a = scale_factor * a
528-
b = scale_factor * b
529-
530-
# Combine the possibly scaled directivity data and the power wave amplitudes
531-
if combined_directivity_data is None:
532-
combined_directivity_data = scaled_directivity_data
533-
else:
534-
combined_directivity_data = combined_directivity_data + scaled_directivity_data
535-
a_sum += a
536-
b_sum += b
537-
538-
# Compute and add power measures to results
539-
power_incident = np.real(0.5 * a_sum * np.conj(a_sum)).sum(dim="port")
540-
power_reflected = np.real(0.5 * b_sum * np.conj(b_sum)).sum(dim="port")
541-
return AntennaMetricsData.from_directivity_data(
542-
combined_directivity_data, power_incident, power_reflected
543-
)
544-
545449
def _extrude_port_structures(self, sim: Simulation) -> Simulation:
546450
"""
547451
Extrude structures intersecting a port plane when a wave port lies on a structure boundary.
@@ -676,9 +580,13 @@ def _clip(i, lo, hi):
676580
)
677581
new_structures.append(new_struct)
678582

679-
# return simulation with added extruded structures
680-
return sim.updated_copy(grid_spec=GridSpec.from_grid(sim.grid), structures=new_structures)
681-
583+
if not mode_sources:
584+
return sim
585+
else:
586+
# return simulation with added extruded structures
587+
return sim.updated_copy(
588+
grid_spec=GridSpec.from_grid(sim.grid), structures=new_structures
589+
)
682590

683-
TerminalComponentModeler.update_forward_refs()
684591

592+
TerminalComponentModeler.update_forward_refs()

0 commit comments

Comments
 (0)