Skip to content

Commit

Permalink
change add_dft_field arguments from freq_min,freq_max to fcen,df
Browse files Browse the repository at this point in the history
  • Loading branch information
oskooi committed Mar 29, 2020
1 parent e9badf2 commit 05da95f
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 37 deletions.
16 changes: 8 additions & 8 deletions doc/docs/Python_User_Interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -1050,9 +1050,9 @@ Given a frequency `omega` and a `Vector3` `pt`, returns the average eigenvalue o
Initialize the component `c` fields using the function `func` which has a single argument, a `Vector3` giving a position and returns a complex number for the value of the field at that point.

**`add_dft_fields(cs, freq_min, freq_max, nfreq, freq, where=None, center=None, size=None, yee_grid=False)`**
**`add_dft_fields(cs, fcen, df, nfreq, freq, where=None, center=None, size=None, yee_grid=False)`**
Given a list of field components `cs`, compute the Fourier transform of these fields for `nfreq` equally spaced frequencies covering the frequency range `freq_min` to `freq_max` or a NumPy array `freq` for arbitrarily spaced frequencies over the `Volume` specified by `where` (default to the entire cell). The volume can also be specified via the `center` and `size` arguments. The default routine interpolates the Fourier transformed fields at the center of each voxel within the specified volume. Alternatively, the exact Fourier transformed fields evaluated at each corresponding Yee grid point is available by setting `yee_grid` to `True`.
Given a list of field components `cs`, compute the Fourier transform of these fields for `nfreq` equally spaced frequencies covering the frequency range `fcen-df/2` to `fcen+df/2` or an array/list `freq` for arbitrarily spaced frequencies over the `Volume` specified by `where` (default to the entire cell). The volume can also be specified via the `center` and `size` arguments. The default routine interpolates the Fourier transformed fields at the center of each voxel within the specified volume. Alternatively, the exact Fourier transformed fields evaluated at each corresponding Yee grid point is available by setting `yee_grid` to `True`.

**`flux_in_box(dir, box=None, center=None, size=None)`**
Expand Down Expand Up @@ -1141,7 +1141,7 @@ Given a bunch of [`FluxRegion`](#fluxregion) objects, you can tell Meep to accum

**`add_flux(fcen, df, nfreq, freq, FluxRegions...)`**
Add a bunch of `FluxRegion`s to the current simulation (initializing the fields if they have not yet been initialized), telling Meep to accumulate the appropriate field Fourier transforms for `nfreq` equally spaced frequencies covering the frequency range `fcen-df/2` to `fcen+df/2` or a NumPy array `freq` for arbitrarily spaced frequencies. Return a *flux object*, which you can pass to the functions below to get the flux spectrum, etcetera.
Add a bunch of `FluxRegion`s to the current simulation (initializing the fields if they have not yet been initialized), telling Meep to accumulate the appropriate field Fourier transforms for `nfreq` equally spaced frequencies covering the frequency range `fcen-df/2` to `fcen+df/2` or an array/list `freq` for arbitrarily spaced frequencies. Return a *flux object*, which you can pass to the functions below to get the flux spectrum, etcetera.

As described in the tutorial, you normally use `add_flux` via statements like:

Expand Down Expand Up @@ -1273,7 +1273,7 @@ A weight factor to multiply the energy density by when it is computed. Default i

**`Simulation.add_energy(fcen, df, nfreq, freq, EnergyRegions...)`**
Add a bunch of `EnergyRegion`s to the current simulation (initializing the fields if they have not yet been initialized), telling Meep to accumulate the appropriate field Fourier transforms for `nfreq` equally spaced frequencies covering the frequency range `fcen-df/2` to `fcen+df/2` or a NumPy array `freq` for arbitrarily spaced frequencies. Return an *energy object*, which you can pass to the functions below to get the energy spectrum, etcetera.
Add a bunch of `EnergyRegion`s to the current simulation (initializing the fields if they have not yet been initialized), telling Meep to accumulate the appropriate field Fourier transforms for `nfreq` equally spaced frequencies covering the frequency range `fcen-df/2` to `fcen+df/2` or an array/list `freq` for arbitrarily spaced frequencies. Return an *energy object*, which you can pass to the functions below to get the energy spectrum, etcetera.

As for energy regions, you normally use `add_energy` via statements like:

Expand Down Expand Up @@ -1355,7 +1355,7 @@ In most circumstances, you should define a set of `ForceRegion`s whose union is

**`Simulation.add_force(fcen, df, nfreq, freq, ForceRegions...)`**
Add a bunch of `ForceRegion`s to the current simulation (initializing the fields if they have not yet been initialized), telling Meep to accumulate the appropriate field Fourier transforms for `nfreq` equally spaced frequencies covering the frequency range `fcen-df/2` to `fcen+df/2` or a NumPy array `freq` for arbitrarily spaced frequencies. Return a `force`object, which you can pass to the functions below to get the force spectrum, etcetera.
Add a bunch of `ForceRegion`s to the current simulation (initializing the fields if they have not yet been initialized), telling Meep to accumulate the appropriate field Fourier transforms for `nfreq` equally spaced frequencies covering the frequency range `fcen-df/2` to `fcen+df/2` or an array/list `freq` for arbitrarily spaced frequencies. Return a `force`object, which you can pass to the functions below to get the force spectrum, etcetera.

As for force regions, you normally use `add_force` via statements like:

Expand Down Expand Up @@ -1415,15 +1415,15 @@ Meep can also calculate the LDOS (local density of states) spectrum, as describe

**`Ldos(fcen, df, nfreq, freq)`**
Create an LDOS object with either frequency bandwidth `df` centered at `fcen`, at `nfreq` equally spaced frequency points or a NumPy array `freq` for arbitrarily spaced frequencies. This can be passed to the `dft_ldos` step function below, and has the properties `freq_min`, `nfreq` and `dfreq`.
Create an LDOS object with either frequency bandwidth `df` centered at `fcen`, at `nfreq` equally spaced frequency points or an array/list `freq` for arbitrarily spaced frequencies. This can be passed to the `dft_ldos` step function below, and has the properties `freq_min`, `nfreq` and `dfreq`.

**`get_ldos_freqs(ldos)`**
Given an LDOS object, returns a list of the frequencies that it is computing the spectrum for.

**`dft_ldos(fcen=None, df=None, nfreq=None, freq=None, ldos=None)`**
Compute the power spectrum of the sources (usually a single point dipole source), normalized to correspond to the LDOS, in either a frequency bandwidth `df` centered at `fcen`, at `nfreq` equally spaced frequency points or a NumPy array `freq` for arbitrarily spaced frequencies. One can also pass in an `ldos` created with `DftLdos` as `dft_ldos(ldos=my_ldos)`.
Compute the power spectrum of the sources (usually a single point dipole source), normalized to correspond to the LDOS, in either a frequency bandwidth `df` centered at `fcen`, at `nfreq` equally spaced frequency points or an array/list `freq` for arbitrarily spaced frequencies. One can also pass in an `ldos` created with `DftLdos` as `dft_ldos(ldos=my_ldos)`.

The resulting spectrum is outputted as comma-delimited text, prefixed by `ldos:,`, and is also stored in the `ldos_data` variable of the `Simulation` object after the `run` is complete.

Expand All @@ -1445,7 +1445,7 @@ There are three steps to using the near-to-far-field feature: first, define the

**`add_near2far(fcen, df, nfreq, freq, Near2FarRegions..., nperiods=1)`**
Add a bunch of `Near2FarRegion`s to the current simulation (initializing the fields if they have not yet been initialized), telling Meep to accumulate the appropriate field Fourier transforms for `nfreq` equally spaced frequencies covering the frequency range `fcen-df/2` to `fcen+df/2` or a NumPy array `freq` for arbitrarily spaced frequencies. Return a `near2far` object, which you can pass to the functions below to get the far fields.
Add a bunch of `Near2FarRegion`s to the current simulation (initializing the fields if they have not yet been initialized), telling Meep to accumulate the appropriate field Fourier transforms for `nfreq` equally spaced frequencies covering the frequency range `fcen-df/2` to `fcen+df/2` or an array/list `freq` for arbitrarily spaced frequencies. Return a `near2far` object, which you can pass to the functions below to get the far fields.

Each `Near2FarRegion` is identical to `FluxRegion` except for the name: in 3d, these give a set of planes (**important:** all these "near surfaces" must lie in a single *homogeneous* material with *isotropic* ε and μ — and they should *not* lie in the PML regions) surrounding the source(s) of outgoing radiation that you want to capture and convert to a far field. Ideally, these should form a closed surface, but in practice it is sufficient for the `Near2FarRegion`s to capture all of the radiation in the direction of the far-field points. **Important:** as for flux computations, each `Near2FarRegion` should be assigned a `weight` of ±1 indicating the direction of the outward normal relative to the +coordinate direction. So, for example, if you have six regions defining the six faces of a cube, i.e. the faces in the +x, -x, +y, -y, +z, and -z directions, then they should have weights +1, -1, +1, -1, +1, and -1 respectively. Note that, neglecting discretization errors, all near-field surfaces that enclose the same outgoing fields are equivalent and will yield the same far fields with a discretization-induced difference that vanishes with increasing resolution etc.

Expand Down
42 changes: 21 additions & 21 deletions python/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1634,15 +1634,15 @@ def _evaluate_dft_objects(self):

def add_dft_fields(self, *args, **kwargs):
components = args[0]
if isinstance(args[1],(int,float)) and isinstance(args[2],(int,float)) and isinstance(args[3],int):
freq_min = args[1]
freq_max = args[2]
if len(args) == 4 and isinstance(args[1],(int,float)) and isinstance(args[2],(int,float)) and isinstance(args[3],int):
fcen = args[1]
df = args[2]
nfreq = args[3]
freq = [0.5*(freq_min+freq_max)] if nfreq == 1 else np.linspace(freq_min,freq_max,nfreq)
elif isinstance(args[1],(np.ndarray,list)):
freq = [fcen] if nfreq == 1 else np.linspace(fcen-0.5*df,fcen+0.5*df,nfreq)
elif len(args) == 2 and isinstance(args[1],(np.ndarray,list)):
freq = args[1]
else:
raise TypeError("add_dft_fields only accepts freq_min,freq_max,nfreq (3 numbers) or freq (array/list)")
raise TypeError("add_dft_fields only accepts fcen,df,nfreq (3 numbers) or freq (array/list)")
where = kwargs.get('where', None)
center = kwargs.get('center', None)
size = kwargs.get('size', None)
Expand Down Expand Up @@ -1681,13 +1681,13 @@ def get_dft_data(self, dft_chunk):
return arr

def add_near2far(self, *args, **kwargs):
if isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
if len(args) > 3 and isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
fcen = args[0]
df = args[1]
nfreq = args[2]
freq = [fcen] if nfreq == 1 else np.linspace(fcen-0.5*df,fcen+0.5*df,nfreq)
near2fars = args[3:]
elif isinstance(args[0],np.ndarray):
elif len(args) > 1 and isinstance(args[0],np.ndarray):
freq = args[0]
near2fars = args[1:]
else:
Expand Down Expand Up @@ -1809,13 +1809,13 @@ def load_minus_near2far_data(self, n2f, n2fdata):
n2f.scale_dfts(complex(-1.0))

def add_force(self, *args):
if isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
if len(args) > 3 and isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
fcen = args[0]
df = args[1]
nfreq = args[2]
freq = [fcen] if nfreq == 1 else np.linspace(fcen-0.5*df,fcen+0.5*df,nfreq)
forces = args[3:]
elif isinstance(args[0],np.ndarray):
elif len(args) > 1 and isinstance(args[0],np.ndarray):
freq = args[0]
forces = args[1:]
else:
Expand Down Expand Up @@ -1862,13 +1862,13 @@ def load_minus_force_data(self, force, fdata):
force.scale_dfts(complex(-1.0))

def add_flux(self, *args):
if isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
if len(args) > 3 and isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
fcen = args[0]
df = args[1]
nfreq = args[2]
freq = [fcen] if nfreq == 1 else np.linspace(fcen-0.5*df,fcen+0.5*df,nfreq)
fluxes = args[3:]
elif isinstance(args[0],np.ndarray):
elif len(args) > 1 and isinstance(args[0],np.ndarray):
freq = args[0]
fluxes = args[1:]
else:
Expand All @@ -1883,13 +1883,13 @@ def _add_flux(self, freq, fluxes):
return self._add_fluxish_stuff(self.fields.add_dft_flux, freq, fluxes)

def add_mode_monitor(self, *args):
if isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
if len(args) > 3 and isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
fcen = args[0]
df = args[1]
nfreq = args[2]
freq = [fcen] if nfreq == 1 else np.linspace(fcen-0.5*df,fcen+0.5*df,nfreq)
fluxes = args[3:]
elif isinstance(args[0],np.ndarray):
elif len(args) > 1 and isinstance(args[0],np.ndarray):
freq = args[0]
fluxes = args[1:]
else:
Expand Down Expand Up @@ -3026,12 +3026,12 @@ def output_sfield_p(sim):


def Ldos(*args):
if isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
if len(args) == 3 and isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
fcen = args[0]
df = args[1]
nfreq = args[2]
freq = [fcen] if nfreq == 1 else np.linspace(fcen-0.5*df,fcen+0.5*df,nfreq)
elif isinstance(args[0],np.ndarray):
elif len(args) == 1 and isinstance(args[0],np.ndarray):
freq = args[0]
else:
raise TypeError("Ldos only accepts fcen,df,nfreq (3 numbers) or freq (array/list)")
Expand All @@ -3041,18 +3041,18 @@ def Ldos(*args):

def dft_ldos(*args, **kwargs):
ldos = kwargs.get('ldos', None)
if len(args) < 3 and ldos is None:
raise ValueError("dft_ldos accepts either fcen,df,nfreq (3 numbers) or an ldos object (keyword argument)")
if ldos is None:
if isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
if len(args) == 3 and isinstance(args[0],(int,float)) and isinstance(args[1],(int,float)) and isinstance(args[2],int):
fcen = args[0]
df = args[1]
nfreq = args[2]
freq = [fcen] if nfreq == 1 else np.linspace(fcen-0.5*df,fcen+0.5*df,nfreq)
elif isinstance(args[0],np.ndarray):
elif len(args) == 1 and isinstance(args[0],(np.ndarray,list)):
freq = args[0]
elif len(args) == 1:
raise ValueError("dft_ldos accepts either fcen,df,nfreq (3 numbers) or freq (array/list) or an ldos object (keyword argument)")
else:
raise TypeError("dft_ldos only accepts fcen,df,nfreq (3 numbers) or freq (array/list)")
raise TypeError("dft_ldos only accepts fcen,df,nfreq (3 numbers) or freq (array/list) or an ldos object (keyword argument)")
ldos = mp._dft_ldos(freq)

def _ldos(sim, todo):
Expand Down
2 changes: 1 addition & 1 deletion python/tests/array_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def vec_func(r):
symmetries=symmetries,
boundary_layers=pml_layers)

dft_obj = sim.add_dft_fields([mp.Ez], fcen, fcen, 1, where=nonpml_vol)
dft_obj = sim.add_dft_fields([mp.Ez], fcen, 0, 1, where=nonpml_vol)
sim.run(until_after_sources=100)

Ez = sim.get_dft_array(dft_obj, mp.Ez, 0)
Expand Down
10 changes: 5 additions & 5 deletions python/tests/dft_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,22 @@ def init(self):
def test_use_centered_grid(self):
sim = self.init()
sim.init_sim()
dft_fields = sim.add_dft_fields([mp.Ez], self.fcen, self.fcen, 1, yee_grid=True)
dft_fields = sim.add_dft_fields([mp.Ez], self.fcen, 0, 1, yee_grid=True)
sim.run(until=100)

def test_get_dft_array(self):
sim = self.init()
sim.init_sim()
dft_fields = sim.add_dft_fields([mp.Ez], self.fcen, self.fcen, 1)
dft_fields = sim.add_dft_fields([mp.Ez], self.fcen, 0, 1)
fr = mp.FluxRegion(mp.Vector3(), size=mp.Vector3(self.sxy, self.sxy), direction=mp.X)
dft_flux = sim.add_flux(self.fcen, 0, 1, fr)

# volumes with zero thickness in x and y directions to test collapsing
# of empty dimensions in DFT array and HDF5 output routines
thin_x_volume = mp.Volume(center=mp.Vector3(0.35*self.sxy), size=mp.Vector3(y=0.8*self.sxy))
thin_x_flux = sim.add_dft_fields([mp.Ez], self.fcen, self.fcen, 1, where=thin_x_volume)
thin_x_flux = sim.add_dft_fields([mp.Ez], self.fcen, 0, 1, where=thin_x_volume)
thin_y_volume = mp.Volume(center=mp.Vector3(y=0.25*self.sxy), size=mp.Vector3(x=self.sxy))
thin_y_flux = sim.add_flux(self.fcen, self.fcen, 1, mp.FluxRegion(volume=thin_y_volume))
thin_y_flux = sim.add_flux(self.fcen, 0, 1, mp.FluxRegion(volume=thin_y_volume))

sim.run(until_after_sources=100)

Expand Down
2 changes: 1 addition & 1 deletion python/tests/modal_volume_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def get_modal_volume(sim, box=None, dft_cell=None, nf=0):
# mv_box is the region within which we compute modal volume
mv_box_size = mp.Vector3(L_inner, L_inner, mp.inf)
mv_box = mp.Volume(center=origin, size=mv_box_size)
dft_cell = sim.add_dft_fields([mp.Ex, mp.Ey, mp.Ez], fcen-df, fcen+df, 3, where=mv_box)
dft_cell = sim.add_dft_fields([mp.Ex, mp.Ey, mp.Ez], fcen, 2*df, 3, where=mv_box)

# Timestep until the sources are finished, pausing at fixed intervals to
# compare the modal volume within mv_box as computed from time-domain fields
Expand Down
2 changes: 1 addition & 1 deletion python/tests/n2f_periodic.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def test_nea2far_periodic(self):
symmetries=symmetries)

n2f_obj = sim.add_near2far(fcen, 0, 1, mp.Near2FarRegion(center=n2f_pt, size=mp.Vector3(y=sy)), nperiods=10)
dft_obj = sim.add_dft_fields([mp.Ez], fcen, fcen, 1, center=dft_pt, size=mp.Vector3(y=sy))
dft_obj = sim.add_dft_fields([mp.Ez], fcen, 0, 1, center=dft_pt, size=mp.Vector3(y=sy))

sim.run(until_after_sources=300)

Expand Down

0 comments on commit 05da95f

Please sign in to comment.