| 
21 | 21 | from tidy3d.constants import HERTZ  | 
22 | 22 | from tidy3d.exceptions import ValidationError  | 
23 | 23 | from tidy3d.log import log  | 
 | 24 | +from tidy3d.packaging import supports_microwave, tidy3d_microwave  | 
24 | 25 | 
 
  | 
25 | 26 | # how many units of ``twidth`` from the ``offset`` until a gaussian pulse is considered "off"  | 
26 | 27 | END_TIME_FACTOR_GAUSSIAN = 10  | 
@@ -605,4 +606,67 @@ def end_time(self) -> Optional[float]:  | 
605 | 606 |         return np.max(t_non_zero)  | 
606 | 607 | 
 
  | 
607 | 608 | 
 
  | 
608 |  | -SourceTimeType = Union[GaussianPulse, ContinuousWave, CustomSourceTime]  | 
 | 609 | +class BroadbandPulse(SourceTime):  | 
 | 610 | +    """A source time injecting significant energy in the entire custom frequency range."""  | 
 | 611 | + | 
 | 612 | +    freq_range: FreqBound = pydantic.Field(  | 
 | 613 | +        ...,  | 
 | 614 | +        title="Frequency Range",  | 
 | 615 | +        description="Frequency range where the pulse should have significant energy.",  | 
 | 616 | +        units=HERTZ,  | 
 | 617 | +    )  | 
 | 618 | +    minimum_amplitude: float = pydantic.Field(  | 
 | 619 | +        0.3,  | 
 | 620 | +        title="Minimum Amplitude",  | 
 | 621 | +        description="Minimum amplitude of the pulse relative to the peak amplitude in the frequency range.",  | 
 | 622 | +        gt=0.05,  | 
 | 623 | +        lt=0.5,  | 
 | 624 | +    )  | 
 | 625 | +    offset: float = pydantic.Field(  | 
 | 626 | +        5.0,  | 
 | 627 | +        title="Offset",  | 
 | 628 | +        description="Time delay of the maximum value of the "  | 
 | 629 | +        "pulse in units of 1 / (``2pi * fwidth``).",  | 
 | 630 | +        ge=2.5,  | 
 | 631 | +    )  | 
 | 632 | + | 
 | 633 | +    @cached_property  | 
 | 634 | +    @supports_microwave  | 
 | 635 | +    def _source(self):  | 
 | 636 | +        """Implementation of broadband pulse."""  | 
 | 637 | +        return tidy3d_microwave["mod"].BroadbandPulse(  | 
 | 638 | +            fmin=self.freq_range[0],  | 
 | 639 | +            fmax=self.freq_range[1],  | 
 | 640 | +            minRelAmp=self.minimum_amplitude,  | 
 | 641 | +            amp=self.amplitude,  | 
 | 642 | +            phase=self.phase,  | 
 | 643 | +            offset=self.offset,  | 
 | 644 | +        )  | 
 | 645 | + | 
 | 646 | +    def end_time(self) -> float:  | 
 | 647 | +        """Time after which the source is effectively turned off / close to zero amplitude."""  | 
 | 648 | +        return self._source.end_time(END_TIME_FACTOR_GAUSSIAN)  | 
 | 649 | + | 
 | 650 | +    def amp_time(self, time: float) -> complex:  | 
 | 651 | +        """Complex-valued source amplitude as a function of time."""  | 
 | 652 | +        return self._source.amp_time(time)  | 
 | 653 | + | 
 | 654 | +    def amp_freq(self, freq: float) -> complex:  | 
 | 655 | +        """Complex-valued source amplitude as a function of frequency."""  | 
 | 656 | +        return self._source.amp_freq(freq)  | 
 | 657 | + | 
 | 658 | +    def frequency_range_sigma(self, sigma: float = DEFAULT_SIGMA) -> FreqBound:  | 
 | 659 | +        """Frequency range where the source amplitude is within ``exp(-sigma**2/2)`` of the peak amplitude."""  | 
 | 660 | +        return self._source.frequency_range(sigma)  | 
 | 661 | + | 
 | 662 | +    def frequency_range(self, num_fwidth: float = DEFAULT_SIGMA) -> FreqBound:  | 
 | 663 | +        """Frequency range where the source amplitude is within ``exp(-sigma**2/2)`` of the peak amplitude."""  | 
 | 664 | +        return self.frequency_range_sigma(num_fwidth)  | 
 | 665 | + | 
 | 666 | +    @cached_property  | 
 | 667 | +    def _freq0(self) -> float:  | 
 | 668 | +        """Central frequency from frequency range."""  | 
 | 669 | +        return np.mean(self.freq_range)  | 
 | 670 | + | 
 | 671 | + | 
 | 672 | +SourceTimeType = Union[GaussianPulse, ContinuousWave, CustomSourceTime, BroadbandPulse]  | 
0 commit comments