Skip to content

Commit

Permalink
Expose more ldos data (#581)
Browse files Browse the repository at this point in the history
* Expose more ldos data

* Rename omega to freqs and make get_ldos_freqs a method of Ldos
  • Loading branch information
ChristopherHogan authored and stevengj committed Nov 6, 2018
1 parent 1e628c9 commit 8b36b2f
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 12 deletions.
12 changes: 8 additions & 4 deletions doc/docs/Python_User_Interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -1180,13 +1180,17 @@ As `load_force_data`, but negates the Fourier-transformed fields after they are

Meep can also calculate the LDOS (local density of states) spectrum, as described in [Tutorial/Local Density of States](Python_Tutorials/Local_Density_of_States.md). To do this, you simply pass the following step function to your `run` command:

**`dft_ldos(fcen, df, nfreq)`**
**`Ldos(fcen, df, nfreq)`**
Compute the power spectrum of the sources (usually a single point dipole source), normalized to correspond to the LDOS, in a frequency bandwidth `df` centered at `fcen`, at `nfreq` frequency points.
Create an LDOS object with frequency bandwidth `df` centered at `fcen`, at `nfreq` frequency points. This can be passed to the `dft_ldos` step function below, and has the properties `freq_min`, `nfreq` and `dfreq`.

**`get_ldos_freqs(ldos)`**
**`freqs()`**
Given an ldos object, returns a list of the frequencies that it is computing the spectrum for.
Method of `Ldos` that returns a list of the frequencies that this `Ldos` instance is computing the spectrum for.

**`dft_ldos(fcen=None, df=None, nfreq=None, ldos=None)`**
Compute the power spectrum of the sources (usually a single point dipole source), normalized to correspond to the LDOS, in a frequency bandwidth `df` centered at `fcen`, at `nfreq` frequency points. 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 Down
31 changes: 30 additions & 1 deletion python/meep.i
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,35 @@ void _get_eigenmode(meep::fields *f, double omega_src, meep::direction d, const
bool verbose, double kdom[3]);
#endif // HAVE_MPB

// Make omega members of meep::dft_ldos available as 'freq' in python
%extend meep::dft_ldos {

double get_omega_min() {
return $self->omega_min;
}
double get_domega() {
return $self->domega;
}
int get_Nomega() {
return $self->Nomega;
}
%pythoncode %{
def freqs(self):
import math
import numpy as np
start = self.omega_min / (2 * math.pi)
stop = start + (self.domega / (2 * math.pi)) * self.Nomega
return np.linspace(start, stop, num=self.Nomega, endpoint=False).tolist()

__swig_getmethods__["freq_min"] = get_omega_min
__swig_getmethods__["nfreq"] = get_Nomega
__swig_getmethods__["dfreq"] = get_domega
if _newclass: freq_min = property(get_omega_min)
if _newclass: nfreq = property(get_Nomega)
if _newclass: dfreq = property(get_domega)
%}
}

extern boolean point_in_objectp(vector3 p, GEOMETRIC_OBJECT o);
extern boolean point_in_periodic_objectp(vector3 p, GEOMETRIC_OBJECT o);
void display_geometric_object_info(int indentby, GEOMETRIC_OBJECT o);
Expand Down Expand Up @@ -1266,6 +1295,7 @@ kpoint_list get_eigenmode_coefficients_and_kpoints(meep::fields *f, meep::dft_fl
)
from .simulation import (
Absorber,
Ldos,
FluxRegion,
ForceRegion,
Harminv,
Expand Down Expand Up @@ -1298,7 +1328,6 @@ kpoint_list get_eigenmode_coefficients_and_kpoints(meep::fields *f, meep::dft_fl
get_force_freqs,
get_forces,
get_near2far_freqs,
get_ldos_freqs,
in_point,
in_volume,
interpolate,
Expand Down
15 changes: 8 additions & 7 deletions python/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2160,14 +2160,15 @@ def output_sfield_p(sim):
sim.output_component(mp.Sp)


def get_ldos_freqs(f):
start = f.omega_min / (2 * math.pi)
stop = start + (f.domega / (2 * math.pi)) * f.Nomega
return np.linspace(start, stop, num=f.Nomega, endpoint=False).tolist()
def Ldos(fcen, df, nfreq):
return mp._dft_ldos(fcen - df / 2, fcen + df / 2, nfreq)


def dft_ldos(fcen, df, nfreq):
ldos = mp._dft_ldos(fcen - df / 2, fcen + df / 2, nfreq)
def dft_ldos(fcen=None, df=None, nfreq=None, ldos=None):
if ldos is None:
if fcen is None or df is None or nfreq is None:
raise ValueError("Either fcen, df, and nfreq, or an Ldos is required for dft_ldos")
ldos = mp._dft_ldos(fcen - df / 2, fcen + df / 2, nfreq)

def _ldos(sim, todo):
if todo == 'step':
Expand All @@ -2176,7 +2177,7 @@ def _ldos(sim, todo):
sim.ldos_data = mp._dft_ldos_ldos(ldos)
sim.ldos_Fdata = mp._dft_ldos_F(ldos)
sim.ldos_Jdata = mp._dft_ldos_J(ldos)
display_csv(sim, 'ldos', zip(get_ldos_freqs(ldos), sim.ldos_data))
display_csv(sim, 'ldos', zip(ldos.freqs(), sim.ldos_data))
return _ldos


Expand Down
18 changes: 18 additions & 0 deletions python/tests/ldos.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import math
import unittest

import meep as mp
Expand Down Expand Up @@ -34,6 +35,23 @@ def test_ldos(self):

self.assertAlmostEqual(self.sim.ldos_data[0], 1.011459560620368)

def test_ldos_user_object(self):
ldos = mp.Ldos(self.fcen, 0, 1)
self.sim.run(
mp.dft_ldos(ldos=ldos),
until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, mp.Vector3(), 1e-6)
)

self.assertAlmostEqual(self.sim.ldos_data[0], 1.011459560620368)
freqs = ldos.freqs()
self.assertEqual(ldos.freq_min, freqs[0] * 2 * math.pi)
self.assertEqual(ldos.nfreq, 1)
self.assertEqual(ldos.dfreq, 0)

def test_invalid_dft_ldos(self):
with self.assertRaises(ValueError):
self.sim.run(mp.dft_ldos(mp.Ldos(self.fcen, 0, 1)), until=200)


if __name__ == '__main__':
unittest.main()

0 comments on commit 8b36b2f

Please sign in to comment.