@@ -71,33 +71,10 @@ def terminal_construct_smatrix(
7171 source_indices = list (modeler_data .modeler .matrix_indices_source )
7272 run_source_indices = list (modeler_data .modeler .matrix_indices_run_sim )
7373
74- values = np .zeros (
75- (len (modeler_data .modeler .freqs ), len (monitor_indices ), len (source_indices )),
76- dtype = complex ,
77- )
78- coords = {
79- "f" : np .array (modeler_data .modeler .freqs ),
80- "port_out" : monitor_indices ,
81- "port_in" : source_indices ,
82- }
83- a_matrix = TerminalPortDataArray (values , coords = coords )
84- b_matrix = a_matrix .copy (deep = True )
85-
86- # Tabulate the reference impedances at each port and frequency
87- port_impedances = port_reference_impedances (modeler_data = modeler_data )
88-
89- for source_index in run_source_indices :
90- port , mode_index = modeler_data .modeler .network_dict [source_index ]
91- sim_data = modeler_data .data [
92- modeler_data .modeler .get_task_name (port = port , mode_index = mode_index )
93- ]
94- a , b = modeler_data .compute_wave_amplitudes_at_each_port (
95- port_reference_impedances = port_impedances , sim_data = sim_data , s_param_def = s_param_def
96- )
97-
98- indexer = {"port_in" : source_index }
99- a_matrix = a_matrix ._with_updated_data (data = a .data , coords = indexer )
100- b_matrix = b_matrix ._with_updated_data (data = b .data , coords = indexer )
74+ if s_param_def == "pseudo" :
75+ a_matrix , b_matrix = modeler_data .port_pseudo_wave_matrices
76+ else :
77+ a_matrix , b_matrix = modeler_data .port_power_wave_matrices
10178
10279 # If excitation is assumed ideal, a_matrix is assumed to be diagonal
10380 # and the explicit inverse can be avoided. When only a subset of excitations
@@ -109,6 +86,8 @@ def terminal_construct_smatrix(
10986 # Scale each column by the corresponding diagonal entry
11087 s_matrix = b_matrix / a_diag [:, np .newaxis , :]
11188
89+ # Expand the smatrix using user defined mappings
90+ s_matrix_expanded = s_matrix .reindex (port_in = source_indices , fill_value = 0.0 )
11291 # element can be determined by user-defined mapping
11392 for (row_in , col_in ), (row_out , col_out ), mult_by in modeler_data .modeler .element_mappings :
11493 coords_from = {
@@ -119,9 +98,9 @@ def terminal_construct_smatrix(
11998 "port_in" : col_out ,
12099 "port_out" : row_out ,
121100 }
122- data = mult_by * s_matrix .loc [coords_from ].data
123- s_matrix = s_matrix ._with_updated_data (data = data , coords = coords_to )
124- return s_matrix
101+ data = mult_by * s_matrix_expanded .loc [coords_from ].data
102+ s_matrix_expanded = s_matrix_expanded ._with_updated_data (data = data , coords = coords_to )
103+ return s_matrix_expanded
125104
126105
127106def port_reference_impedances (modeler_data : TerminalComponentModelerData ) -> PortDataArray :
@@ -179,32 +158,29 @@ def port_reference_impedances(modeler_data: TerminalComponentModelerData) -> Por
179158 return port_impedances
180159
181160
182- def compute_wave_amplitudes_at_each_port (
161+ def _compute_port_voltages_currents (
183162 modeler : TerminalComponentModeler ,
184- port_reference_impedances : PortDataArray ,
185163 sim_data : SimulationData ,
186- s_param_def : SParamDef = "pseudo" ,
187164) -> tuple [PortDataArray , PortDataArray ]:
188- """Compute the incident and reflected amplitudes at each port .
165+ """Compute voltage and current values at all ports for a single simulation .
189166
190- The computed amplitudes have not been normalized.
167+ This function calculates the voltage and current at each monitor port from the
168+ electromagnetic field data in a single simulation result. The voltages and currents
169+ are computed according to the specific port type (e.g., lumped, wave) and are used
170+ as inputs for subsequent wave amplitude calculations.
191171
192172 Parameters
193173 ----------
194174 modeler : :class:`.TerminalComponentModeler`
195- The component modeler defining the ports and simulation settings.
196- port_reference_impedances : :class:`.PortDataArray`
197- Reference impedance at each port.
175+ The component modeler containing port definitions and network mapping.
198176 sim_data : :class:`.SimulationData`
199- Results from a single simulation run.
200- s_param_def : SParamDef
201- The type of waves computed, either pseudo waves defined by Equation 53 and
202- Equation 54 in [1], or power waves defined by Equation 4.67 in [2].
177+ Simulation results containing the electromagnetic field data.
203178
204179 Returns
205180 -------
206181 tuple[:class:`.PortDataArray`, :class:`.PortDataArray`]
207- Incident (a) and reflected (b) wave amplitudes at each port.
182+ A tuple containing the voltage and current arrays with dimensions (f, port),
183+ where voltages and currents are computed for each frequency and monitor port.
208184 """
209185 network_indices = list (modeler .matrix_indices_monitor )
210186 values = np .zeros (
@@ -218,18 +194,56 @@ def compute_wave_amplitudes_at_each_port(
218194
219195 V_matrix = PortDataArray (values , coords = coords )
220196 I_matrix = V_matrix .copy (deep = True )
221- a = V_matrix .copy (deep = True )
222- b = V_matrix .copy (deep = True )
223197
224198 for network_index in network_indices :
225199 port , mode_index = modeler .network_dict [network_index ]
226200 V_out , I_out = compute_port_VI (port , sim_data )
227201 indexer = {"port" : network_index }
228202 V_matrix = V_matrix ._with_updated_data (data = V_out .data , coords = indexer )
229203 I_matrix = I_matrix ._with_updated_data (data = I_out .data , coords = indexer )
204+ return (V_matrix , I_matrix )
205+
206+
207+ def _compute_wave_amplitudes_from_VI (
208+ port_reference_impedances : PortDataArray ,
209+ port_voltages : PortDataArray ,
210+ port_currents : PortDataArray ,
211+ s_param_def : SParamDef = "pseudo" ,
212+ ) -> tuple [PortDataArray , PortDataArray ]:
213+ """Convert port voltages and currents to incident and reflected wave amplitudes.
214+
215+ This function transforms voltage and current data at each port into forward-traveling
216+ (incident, 'a') and backward-traveling (reflected, 'b') wave amplitudes using the
217+ specified wave definition. The conversion handles impedance sign consistency and
218+ applies the appropriate normalization based on the chosen S-parameter definition.
219+
220+ The wave amplitudes are computed using:
221+ - Pseudo waves: Equations 53-54 from Marks and Williams [1]
222+ - Power waves: Equation 4.67 from Pozar [2]
230223
231- V_numpy = V_matrix .values
232- I_numpy = I_matrix .values
224+ Parameters
225+ ----------
226+ port_reference_impedances : :class:`.PortDataArray`
227+ Reference impedance values for each port with dimensions (f, port).
228+ port_voltages : :class:`.PortDataArray`
229+ Voltage values at each port with dimensions (f, port).
230+ port_currents : :class:`.PortDataArray`
231+ Current values at each port with dimensions (f, port).
232+ s_param_def : SParamDef, optional
233+ Wave definition type: "pseudo" for pseudo waves or "power" for power waves.
234+ Defaults to "pseudo".
235+
236+ Returns
237+ -------
238+ tuple[:class:`.PortDataArray`, :class:`.PortDataArray`]
239+ A tuple containing the incident (a) and reflected (b) wave amplitude arrays,
240+ each with dimensions (f, port) representing the wave amplitudes at each
241+ frequency and port.
242+ """
243+ a = port_voltages .copy (deep = True )
244+ b = port_currents .copy (deep = True )
245+ V_numpy = port_voltages .values
246+ I_numpy = port_currents .values
233247 Z_numpy = port_reference_impedances .values
234248
235249 # Check to make sure sign is consistent for all impedance values
@@ -254,6 +268,41 @@ def compute_wave_amplitudes_at_each_port(
254268 return a , b
255269
256270
271+ def compute_wave_amplitudes_at_each_port (
272+ modeler : TerminalComponentModeler ,
273+ port_reference_impedances : PortDataArray ,
274+ sim_data : SimulationData ,
275+ s_param_def : SParamDef = "pseudo" ,
276+ ) -> tuple [PortDataArray , PortDataArray ]:
277+ """Compute the incident and reflected amplitudes at each port.
278+
279+ The computed amplitudes have not been normalized.
280+
281+ Parameters
282+ ----------
283+ modeler : :class:`.TerminalComponentModeler`
284+ The component modeler defining the ports and simulation settings.
285+ port_reference_impedances : :class:`.PortDataArray`
286+ Reference impedance at each port.
287+ sim_data : :class:`.SimulationData`
288+ Results from a single simulation run.
289+ s_param_def : SParamDef
290+ The type of waves computed, either pseudo waves defined by Equation 53 and
291+ Equation 54 in [1], or power waves defined by Equation 4.67 in [2].
292+
293+ Returns
294+ -------
295+ tuple[:class:`.PortDataArray`, :class:`.PortDataArray`]
296+ Incident (a) and reflected (b) wave amplitudes at each port.
297+ """
298+
299+ port_voltages , port_currents = _compute_port_voltages_currents (modeler , sim_data )
300+
301+ return _compute_wave_amplitudes_from_VI (
302+ port_reference_impedances , port_voltages , port_currents , s_param_def = s_param_def
303+ )
304+
305+
257306def compute_power_wave_amplitudes_at_each_port (
258307 modeler : TerminalComponentModeler ,
259308 port_reference_impedances : PortDataArray ,
0 commit comments