@@ -446,102 +446,6 @@ def get_radiation_monitor_by_name(self, monitor_name: str) -> DirectivityMonitor
446
446
return monitor
447
447
raise Tidy3dKeyError (f"No radiation monitor named '{ monitor_name } '." )
448
448
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
-
545
449
def _extrude_port_structures (self , sim : Simulation ) -> Simulation :
546
450
"""
547
451
Extrude structures intersecting a port plane when a wave port lies on a structure boundary.
@@ -676,9 +580,13 @@ def _clip(i, lo, hi):
676
580
)
677
581
new_structures .append (new_struct )
678
582
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
+ )
682
590
683
- TerminalComponentModeler .update_forward_refs ()
684
591
592
+ TerminalComponentModeler .update_forward_refs ()
0 commit comments