Choose sources and waveforms

Pick the right source and time signal for radiation, scattering, periodic and waveguide problems, and match it to your monitor frequencies.

This guide helps you pick a source and a time signal for a given problem. Every source takes a source_time; frequencies are in hertz and positions in metres. Arguments are listed on the Sources API page.

Pick the waveform#

You wantUse
A spectrum over a band from one runGaussianPulse(frequency=f0, fwidth=df), centred on the band
One frequency in steady stateCW(frequency=f0)
A broadband pulse with no DC contentRickerWavelet(frequency=f0)
A measured or designed signalCustomSourceTime(times=..., amplitudes=...)
pulse = mw.GaussianPulse(frequency=1.5e9, fwidth=0.5e9)
tone = mw.CW(frequency=1.5e9)

Set Simulation.fdtd(frequencies=[...]) to frequencies inside the pulse band. Maxwell picks the time step from the highest frequency the source contains and runs until the pulse has settled, so a very wide fwidth costs more steps. For a CW source, the run length covers the transient plus steady_cycles periods (TimeConfig.auto(steady_cycles=20, transient_cycles=15) by default).

PlaneWave, GaussianBeam, AstigmaticGaussianBeam and ModeSource reject CustomSourceTime.

Radiation from a small antenna or emitter#

A PointDipole drives one electric field component at one point:

dipole = mw.PointDipole(
    position=(0.0, 0.0, 0.0),
    polarization="Ez",
    source_time=mw.GaussianPulse(frequency=1e9, fwidth=0.3e9),
    name="feed",
)

profile="gaussian" (the default) spreads the current with a Gaussian of standard deviation width (metres, default 0.02); profile="ideal" deposits it on the neighbouring Yee samples. Both keep the same integrated current moment. For an antenna with a feed impedance and S11, use a LumpedPort instead (see Lumped ports and RF networks).

Scattering from an object#

Illuminate the object with a plane wave. Use a TFSF box around the object so the scattered field outside the box is separated from the incident wave:

wave = mw.PlaneWave(
    direction=(1.0, 0.0, 0.0),
    polarization=(0.0, 0.0, 1.0),
    source_time=mw.GaussianPulse(frequency=1e9, fwidth=0.3e9),
    injection=mw.TFSF(bounds=((-0.2, 0.2), (-0.2, 0.2), (-0.2, 0.2))),
)

Keep the object entirely inside the TFSF box, and put scattered-field monitors (for example a ClosedSurfaceMonitor for radar cross section) outside it. Without injection, a plane wave is injected softly on a plane near the absorbing boundary on the side it comes from (injection="soft"), which suits transmission and reflection through layers.

GaussianBeam(beam_waist=..., focus=...) and AstigmaticGaussianBeam launch focused beams with the same arguments.

Periodic structures and gratings#

Use a PlaneWave with injection=TFSF.slab(axis="z", bounds=(z0, z1)) on a scene with periodic or Bloch boundaries on x and y. With Bloch boundaries the slab supports oblique incidence with CW, GaussianPulse or RickerWavelet. See Set up grids and boundaries.

Waveguide modes#

ModeSource solves the modes of the cross section on an axis-aligned plane and launches one of them:

mode = mw.ModeSource(
    position=(-0.32, 0.0, 0.0),
    size=(0.0, 0.56, 0.56),        # the zero component is the propagation axis
    mode_index=0,
    direction="+",
    polarization="Ez",
    source_time=mw.GaussianPulse(frequency=1e9, fwidth=0.3e9),
)

For S-parameters, use ModePort or WavePort, which combine the source and the measurement. See Mode ports and S-parameters.

Warning

ModeSource, ModeMonitor and ModePort are experimental.

Your own currents or fields#

UniformCurrentSource(size, polarization, center=...) drives a uniform current over a box. CustomCurrentSource(CurrentDataset(...)) and CustomFieldSource(FieldDataset(...)) take sampled current or field components on coordinate axes, for example a near field exported from another tool.

Several sources#

Add as many sources as you need; they superpose. Each one keeps its own source_time, so you can drive elements of an array with different phases (in radians):

for i, phase in enumerate((0.0, 0.5, 1.0, 1.5)):
    scene.add_source(mw.PointDipole(position=(0.1 * i, 0.0, 0.0), polarization="Ez",
                                    source_time=mw.CW(frequency=1e9, phase=phase), name=f"el{i}"))