From e6f7123f4294d5e42d6e0eb3d4f0246e1ca879ef Mon Sep 17 00:00:00 2001 From: Ardavan Oskooi Date: Tue, 29 Dec 2020 20:38:57 -0800 Subject: [PATCH] re-instate snap argument for do_get_array_slice --- doc/docs/Python_User_Interface.md | 18 ++- python/simulation.py | 206 ++++++++++++++------------- python/tests/dispersive_eigenmode.py | 2 +- python/tests/simulation.py | 8 +- src/array_slice.cpp | 33 +++-- src/meep.hpp | 15 +- tests/Makefile.am | 2 +- tests/array-slice-ll-ref.h5 | Bin 42464 -> 42464 bytes tests/array-slice-ll.cpp | 4 +- 9 files changed, 155 insertions(+), 133 deletions(-) diff --git a/doc/docs/Python_User_Interface.md b/doc/docs/Python_User_Interface.md index d284c3901..ece3b7eda 100644 --- a/doc/docs/Python_User_Interface.md +++ b/doc/docs/Python_User_Interface.md @@ -3349,7 +3349,8 @@ def get_array(self, size=None, cmplx=None, arr=None, - frequency=0): + frequency=0, + snap=False): ```
@@ -3381,7 +3382,15 @@ current simulation time. fetching the same slice repeatedly at different times). + `frequency`: optional frequency point over which the average eigenvalue of the - dielectric and permeability tensors are evaluated (defaults to 0). + $\varepsilon$ and $\mu$ tensors are evaluated (defaults to 0). + ++ `snap`: By default, the elements of the grid slice are obtained using a bilinear + interpolation of the nearest Yee grid points. Empty dimensions of the grid slice + are "collapsed" into a single element. However, if `snap` is set to `True`, this + interpolation behavior is disabled and the grid slice is instead "snapped" + everywhere to the nearest grid point. (Empty slice dimensions are still of size + one.) This feature is mainly useful for comparing results with the + [`output_` routines](#output-functions) (e.g., `output_epsilon`, `output_efield_z`, etc.). For convenience, the following wrappers for `get_array` over the entire cell are available: `get_epsilon()`, `get_mu()`, `get_hpwr()`, `get_dpwr()`, @@ -3389,7 +3398,8 @@ available: `get_epsilon()`, `get_mu()`, `get_hpwr()`, `get_dpwr()`, `get_Xfield_z()`, `get_Xfield_r()`, `get_Xfield_p()` where `X` is one of `h`, `b`, `e`, `d`, or `s`. The routines `get_Xfield_*` all return an array type consistent with the fields (real or complex). The routines `get_epsilon()` and `get_mu()` -accept the optional `frequency` parameter (defaults to 0). +accept the optional argument `frequency` (defaults to 0) and all routines accept +`snap` (defaults to `False`). **Note on array-slice dimensions:** The routines `get_epsilon`, `get_Xfield_z`, etc. use as default `size=meep.Simulation.fields.total_volume()` which for @@ -3457,7 +3467,7 @@ This routine provides geometric information useful for interpreting the arrays returned by `get_array` or `get_dft_array` for the spatial region defined by `vol` or `center`/`size`. In both cases, the return value is a tuple `(x,y,z,w)`, where: -+ `x,y,z` are tuples storing the $x,y,z$ coordinates of the points in the ++ `x,y,z` are 1d NumPy arrays storing the $x,y,z$ coordinates of the points in the grid slice + `w` is a NumPy array of the same dimensions as the array returned by `get_array`/`get_dft_array`, whose entries are the weights in a cubature rule diff --git a/python/simulation.py b/python/simulation.py index ad7f5f857..9a18ca246 100644 --- a/python/simulation.py +++ b/python/simulation.py @@ -3094,7 +3094,7 @@ def h5topng(self, rm_h5, option, *step_funcs): cmd = re.sub(r'\$EPS', self.last_eps_filename, opts) return convert_h5(rm_h5, cmd, *step_funcs) - def get_array(self, component=None, vol=None, center=None, size=None, cmplx=None, arr=None, frequency=0): + def get_array(self, component=None, vol=None, center=None, size=None, cmplx=None, arr=None, frequency=0, snap=False): """ Takes as input a subregion of the cell and the field/material component. The method returns a NumPy array containing values of the field/material at the @@ -3123,7 +3123,15 @@ def get_array(self, component=None, vol=None, center=None, size=None, cmplx=None fetching the same slice repeatedly at different times). + `frequency`: optional frequency point over which the average eigenvalue of the - dielectric and permeability tensors are evaluated (defaults to 0). + $\\varepsilon$ and $\\mu$ tensors are evaluated (defaults to 0). + + + `snap`: By default, the elements of the grid slice are obtained using a bilinear + interpolation of the nearest Yee grid points. Empty dimensions of the grid slice + are "collapsed" into a single element. However, if `snap` is set to `True`, this + interpolation behavior is disabled and the grid slice is instead "snapped" + everywhere to the nearest grid point. (Empty slice dimensions are still of size + one.) This feature is mainly useful for comparing results with the + [`output_` routines](#output-functions) (e.g., `output_epsilon`, `output_efield_z`, etc.). For convenience, the following wrappers for `get_array` over the entire cell are available: `get_epsilon()`, `get_mu()`, `get_hpwr()`, `get_dpwr()`, @@ -3131,7 +3139,8 @@ def get_array(self, component=None, vol=None, center=None, size=None, cmplx=None `get_Xfield_z()`, `get_Xfield_r()`, `get_Xfield_p()` where `X` is one of `h`, `b`, `e`, `d`, or `s`. The routines `get_Xfield_*` all return an array type consistent with the fields (real or complex). The routines `get_epsilon()` and `get_mu()` - accept the optional `frequency` parameter (defaults to 0). + accept the optional argument `frequency` (defaults to 0) and all routines accept + `snap` (defaults to `False`). **Note on array-slice dimensions:** The routines `get_epsilon`, `get_Xfield_z`, etc. use as default `size=meep.Simulation.fields.total_volume()` which for @@ -3179,9 +3188,9 @@ def get_array(self, component=None, vol=None, center=None, size=None, cmplx=None arr = np.zeros(dims, dtype=np.complex128 if cmplx else np.float64) if np.iscomplexobj(arr): - self.fields.get_complex_array_slice(v, component, arr, frequency) + self.fields.get_complex_array_slice(v, component, arr, frequency, snap) else: - self.fields.get_array_slice(v, component, arr, frequency) + self.fields.get_array_slice(v, component, arr, frequency, snap) return arr @@ -3241,7 +3250,7 @@ def get_array_metadata(self, vol=None, center=None, size=None, dft_cell=None, returned by `get_array` or `get_dft_array` for the spatial region defined by `vol` or `center`/`size`. In both cases, the return value is a tuple `(x,y,z,w)`, where: - + `x,y,z` are tuples storing the $x,y,z$ coordinates of the points in the + + `x,y,z` are 1d NumPy arrays storing the $x,y,z$ coordinates of the points in the grid slice + `w` is a NumPy array of the same dimensions as the array returned by `get_array`/`get_dft_array`, whose entries are the weights in a cubature rule @@ -3288,7 +3297,7 @@ def get_array_metadata(self, vol=None, center=None, size=None, dft_cell=None, if return_pw: points=[ mp.Vector3(x,y,z) for x in tics[0] for y in tics[1] for z in tics[2] ] return points,weights - return tics + [weights] + return tuple(tics) + (weights,) def get_array_slice_dimensions(self, component, vol=None, center=None, size=None): """ @@ -3671,153 +3680,150 @@ def output_times(self, fname): fname += '.csv' self.fields.output_times(fname) - def get_epsilon(self,frequency=0,omega=0): - if omega != 0: - frequency = omega - warnings.warn("get_epsilon: omega has been deprecated; use frequency instead", RuntimeWarning) - return self.get_array(component=mp.Dielectric,frequency=frequency) + def get_epsilon(self,frequency=0,snap=False): + return self.get_array(component=mp.Dielectric,frequency=frequency,snap=snap) - def get_mu(self): - return self.get_array(component=mp.Permeability) + def get_mu(self,frequency=0,snap=False): + return self.get_array(component=mp.Permeability,frequency=frequency,snap=snap) - def get_hpwr(self): - return self.get_array(component=mp.H_EnergyDensity) + def get_hpwr(self,snap=False): + return self.get_array(component=mp.H_EnergyDensity,snap=snap) - def get_dpwr(self): - return self.get_array(component=mp.D_EnergyDensity) + def get_dpwr(self,snap=False): + return self.get_array(component=mp.D_EnergyDensity,snap=snap) - def get_tot_pwr(self): - return self.get_array(component=mp.EnergyDensity) + def get_tot_pwr(self,snap=False): + return self.get_array(component=mp.EnergyDensity,snap=snap) - def get_hfield(self): + def get_hfield(self,snap=False): if self.is_cylindrical: - r = self.get_array(mp.Hr, cmplx=not self.fields.is_real) - p = self.get_array(mp.Hp, cmplx=not self.fields.is_real) + r = self.get_array(mp.Hr, cmplx=not self.fields.is_real, snap=snap) + p = self.get_array(mp.Hp, cmplx=not self.fields.is_real, snap=snap) return np.stack([r, p], axis=-1) else: - x = self.get_array(mp.Hx, cmplx=not self.fields.is_real) - y = self.get_array(mp.Hy, cmplx=not self.fields.is_real) - z = self.get_array(mp.Hz, cmplx=not self.fields.is_real) + x = self.get_array(mp.Hx, cmplx=not self.fields.is_real, snap=snap) + y = self.get_array(mp.Hy, cmplx=not self.fields.is_real, snap=snap) + z = self.get_array(mp.Hz, cmplx=not self.fields.is_real, snap=snap) return np.stack([x, y, z], axis=-1) - def get_hfield_x(self): - return self.get_array(mp.Hx, cmplx=not self.fields.is_real) + def get_hfield_x(self,snap=False): + return self.get_array(mp.Hx, cmplx=not self.fields.is_real, snap=snap) - def get_hfield_y(self): - return self.get_array(mp.Hy, cmplx=not self.fields.is_real) + def get_hfield_y(self,snap=False): + return self.get_array(mp.Hy, cmplx=not self.fields.is_real, snap=snap) - def get_hfield_z(self): - return self.get_array(mp.Hz, cmplx=not self.fields.is_real) + def get_hfield_z(self,snap=False): + return self.get_array(mp.Hz, cmplx=not self.fields.is_real, snap=snap) - def get_hfield_r(self): - return self.get_array(mp.Hr, cmplx=not self.fields.is_real) + def get_hfield_r(self,snap=False): + return self.get_array(mp.Hr, cmplx=not self.fields.is_real, snap=snap) - def get_hfield_p(self): - return self.get_array(mp.Hp, cmplx=not self.fields.is_real) + def get_hfield_p(self,snap=False): + return self.get_array(mp.Hp, cmplx=not self.fields.is_real, snap=snap) - def get_bfield(self): + def get_bfield(self,snap=False): if self.is_cylindrical: - r = self.get_array(mp.Br, cmplx=not self.fields.is_real) - p = self.get_array(mp.Bp, cmplx=not self.fields.is_real) + r = self.get_array(mp.Br, cmplx=not self.fields.is_real, snap=snap) + p = self.get_array(mp.Bp, cmplx=not self.fields.is_real, snap=snap) return np.stack([r, p], axis=-1) else: - x = self.get_array(mp.Bx, cmplx=not self.fields.is_real) - y = self.get_array(mp.By, cmplx=not self.fields.is_real) - z = self.get_array(mp.Bz, cmplx=not self.fields.is_real) + x = self.get_array(mp.Bx, cmplx=not self.fields.is_real, snap=snap) + y = self.get_array(mp.By, cmplx=not self.fields.is_real, snap=snap) + z = self.get_array(mp.Bz, cmplx=not self.fields.is_real, snap=snap) return np.stack([x, y, z], axis=-1) - def get_bfield_x(self): - return self.get_array(mp.Bx, cmplx=not self.fields.is_real) + def get_bfield_x(self,snap=False): + return self.get_array(mp.Bx, cmplx=not self.fields.is_real, snap=snap) - def get_bfield_y(self): - return self.get_array(mp.By, cmplx=not self.fields.is_real) + def get_bfield_y(self,snap=False): + return self.get_array(mp.By, cmplx=not self.fields.is_real, snap=snap) - def get_bfield_z(self): - return self.get_array(mp.Bz, cmplx=not self.fields.is_real) + def get_bfield_z(self,snap=False): + return self.get_array(mp.Bz, cmplx=not self.fields.is_real, snap=snap) - def get_bfield_r(self): - return self.get_array(mp.Br, cmplx=not self.fields.is_real) + def get_bfield_r(self,snap=False): + return self.get_array(mp.Br, cmplx=not self.fields.is_real, snap=snap) - def get_bfield_p(self): - return self.get_array(mp.Bp, cmplx=not self.fields.is_real) + def get_bfield_p(self,snap=False): + return self.get_array(mp.Bp, cmplx=not self.fields.is_real, snap=snap) - def get_efield(self): + def get_efield(self,snap=False): if self.is_cylindrical: - r = self.get_array(mp.Er, cmplx=not self.fields.is_real) - p = self.get_array(mp.Ep, cmplx=not self.fields.is_real) + r = self.get_array(mp.Er, cmplx=not self.fields.is_real, snap=snap) + p = self.get_array(mp.Ep, cmplx=not self.fields.is_real, snap=snap) return np.stack([r, p], axis=-1) else: - x = self.get_array(mp.Ex, cmplx=not self.fields.is_real) - y = self.get_array(mp.Ey, cmplx=not self.fields.is_real) - z = self.get_array(mp.Ez, cmplx=not self.fields.is_real) + x = self.get_array(mp.Ex, cmplx=not self.fields.is_real, snap=snap) + y = self.get_array(mp.Ey, cmplx=not self.fields.is_real, snap=snap) + z = self.get_array(mp.Ez, cmplx=not self.fields.is_real, snap=snap) return np.stack([x, y, z], axis=-1) - def get_efield_x(self): - return self.get_array(mp.Ex, cmplx=not self.fields.is_real) + def get_efield_x(self,snap=False): + return self.get_array(mp.Ex, cmplx=not self.fields.is_real, snap=snap) - def get_efield_y(self): - return self.get_array(mp.Ey, cmplx=not self.fields.is_real) + def get_efield_y(self,snap=False): + return self.get_array(mp.Ey, cmplx=not self.fields.is_real, snap=snap) - def get_efield_z(self): - return self.get_array(mp.Ez, cmplx=not self.fields.is_real) + def get_efield_z(self,snap=False): + return self.get_array(mp.Ez, cmplx=not self.fields.is_real, snap=snap) - def get_efield_r(self): - return self.get_array(mp.Er, cmplx=not self.fields.is_real) + def get_efield_r(self,snap=False): + return self.get_array(mp.Er, cmplx=not self.fields.is_real, snap=snap) - def get_efield_p(self): - return self.get_array(mp.Ep, cmplx=not self.fields.is_real) + def get_efield_p(self,snap=False): + return self.get_array(mp.Ep, cmplx=not self.fields.is_real, snap=snap) - def get_dfield(self): + def get_dfield(self,snap=False): if self.is_cylindrical: - r = self.get_array(mp.Dr, cmplx=not self.fields.is_real) - p = self.get_array(mp.Dp, cmplx=not self.fields.is_real) + r = self.get_array(mp.Dr, cmplx=not self.fields.is_real, snap=snap) + p = self.get_array(mp.Dp, cmplx=not self.fields.is_real, snap=snap) return np.stack([r, p], axis=-1) else: - x = self.get_array(mp.Dx, cmplx=not self.fields.is_real) - y = self.get_array(mp.Dy, cmplx=not self.fields.is_real) - z = self.get_array(mp.Dz, cmplx=not self.fields.is_real) + x = self.get_array(mp.Dx, cmplx=not self.fields.is_real, snap=snap) + y = self.get_array(mp.Dy, cmplx=not self.fields.is_real, snap=snap) + z = self.get_array(mp.Dz, cmplx=not self.fields.is_real, snap=snap) return np.stack([x, y, z], axis=-1) - def get_dfield_x(self): - return self.get_array(mp.Dx, cmplx=not self.fields.is_real) + def get_dfield_x(self,snap=False): + return self.get_array(mp.Dx, cmplx=not self.fields.is_real, snap=snap) - def get_dfield_y(self): - return self.get_array(mp.Dy, cmplx=not self.fields.is_real) + def get_dfield_y(self,snap=False): + return self.get_array(mp.Dy, cmplx=not self.fields.is_real, snap=snap) - def get_dfield_z(self): - return self.get_array(mp.Dz, cmplx=not self.fields.is_real) + def get_dfield_z(self,snap=False): + return self.get_array(mp.Dz, cmplx=not self.fields.is_real, snap=snap) - def get_dfield_r(self): - return self.get_array(mp.Dr, cmplx=not self.fields.is_real) + def get_dfield_r(self,snap=False): + return self.get_array(mp.Dr, cmplx=not self.fields.is_real, snap=snap) - def get_dfield_p(self): - return self.get_array(mp.Dp, cmplx=not self.fields.is_real) + def get_dfield_p(self,snap=False): + return self.get_array(mp.Dp, cmplx=not self.fields.is_real, snap=snap) - def get_sfield(self): + def get_sfield(self,snap=False): if self.is_cylindrical: - r = self.get_array(mp.Sr, cmplx=not self.fields.is_real) - p = self.get_array(mp.Sp, cmplx=not self.fields.is_real) + r = self.get_array(mp.Sr, cmplx=not self.fields.is_real, snap=snap) + p = self.get_array(mp.Sp, cmplx=not self.fields.is_real, snap=snap) return np.stack([r, p], axis=-1) else: - x = self.get_array(mp.Sx, cmplx=not self.fields.is_real) - y = self.get_array(mp.Sy, cmplx=not self.fields.is_real) - z = self.get_array(mp.Sz, cmplx=not self.fields.is_real) + x = self.get_array(mp.Sx, cmplx=not self.fields.is_real, snap=snap) + y = self.get_array(mp.Sy, cmplx=not self.fields.is_real, snap=snap) + z = self.get_array(mp.Sz, cmplx=not self.fields.is_real, snap=snap) return np.stack([x, y, z], axis=-1) - def get_sfield_x(self): - return self.get_array(mp.Sx, cmplx=not self.fields.is_real) + def get_sfield_x(self,snap=False): + return self.get_array(mp.Sx, cmplx=not self.fields.is_real, snap=snap) - def get_sfield_y(self): - return self.get_array(mp.Sy, cmplx=not self.fields.is_real) + def get_sfield_y(self,snap=False): + return self.get_array(mp.Sy, cmplx=not self.fields.is_real, snap=snap) - def get_sfield_z(self): - return self.get_array(mp.Sz, cmplx=not self.fields.is_real) + def get_sfield_z(self,snap=False): + return self.get_array(mp.Sz, cmplx=not self.fields.is_real, snap=snap) - def get_sfield_r(self): - return self.get_array(mp.Sr, cmplx=not self.fields.is_real) + def get_sfield_r(self,snap=False): + return self.get_array(mp.Sr, cmplx=not self.fields.is_real, snap=snap) - def get_sfield_p(self): - return self.get_array(mp.Sp, cmplx=not self.fields.is_real) + def get_sfield_p(self,snap=False): + return self.get_array(mp.Sp, cmplx=not self.fields.is_real, snap=snap) def plot2D(self, ax=None, output_plane=None, fields=None, labels=False, diff --git a/python/tests/dispersive_eigenmode.py b/python/tests/dispersive_eigenmode.py index 60521b756..afe20b3f6 100644 --- a/python/tests/dispersive_eigenmode.py +++ b/python/tests/dispersive_eigenmode.py @@ -63,7 +63,7 @@ def verify_output_and_slice(self,material,frequency): sim.init_sim() # Check to make sure the get_slice routine is working with frequency - n_slice = np.sqrt(np.max(sim.get_epsilon(frequency))) + n_slice = np.sqrt(np.max(sim.get_epsilon(frequency=frequency,snap=True))) self.assertAlmostEqual(n,n_slice, places=4) # Check to make sure h5 output is working with frequency diff --git a/python/tests/simulation.py b/python/tests/simulation.py index 883ce050c..b874b3eae 100644 --- a/python/tests/simulation.py +++ b/python/tests/simulation.py @@ -373,10 +373,10 @@ def test_get_array_output(self): mp.output_tot_pwr(sim) mp.output_efield(sim) - eps_arr = sim.get_epsilon() - efield_z_arr = sim.get_efield_z() - energy_arr = sim.get_tot_pwr() - efield_arr = sim.get_efield() + eps_arr = sim.get_epsilon(snap=True) + efield_z_arr = sim.get_efield_z(snap=True) + energy_arr = sim.get_tot_pwr(snap=True) + efield_arr = sim.get_efield(snap=True) fname_fmt = os.path.join(self.temp_dir, 'test_get_array_output-{}-000020.00.h5') diff --git a/src/array_slice.cpp b/src/array_slice.cpp index 14d085be8..74f836fa0 100644 --- a/src/array_slice.cpp +++ b/src/array_slice.cpp @@ -76,6 +76,7 @@ typedef struct { component invmu_cs[3]; direction invmu_ds[3]; + bool snap; } array_slice_data; #define UNUSED(x) (void)x // silence compiler warnings @@ -332,7 +333,7 @@ static void get_array_slice_chunkloop(fields_chunk *fc, int ichnk, component cgr frequency)); if (abs(tr) == 0.0) tr += 4.0; // default inveps == 1 } - fields[i] = IVEC_LOOP_WEIGHT(s0, s1, e0, e1, 1.0) * (4.0 * data->ninveps) / tr; + fields[i] = (data->snap ? 1.0 : IVEC_LOOP_WEIGHT(s0, s1, e0, e1, 1.0)) * (4.0 * data->ninveps) / tr; } else if (cS[i] == Permeability) { complex tr(0.0, 0.0); @@ -344,7 +345,7 @@ static void get_array_slice_chunkloop(fields_chunk *fc, int ichnk, component cgr frequency)); if (abs(tr) == 0.0) tr += 4.0; // default invmu == 1 } - fields[i] = IVEC_LOOP_WEIGHT(s0, s1, e0, e1, 1.0) * (4.0 * data->ninvmu) / tr; + fields[i] = (data->snap ? 1.0 : IVEC_LOOP_WEIGHT(s0, s1, e0, e1, 1.0)) * (4.0 * data->ninvmu) / tr; } else { double f[2]; @@ -355,7 +356,7 @@ static void get_array_slice_chunkloop(fields_chunk *fc, int ichnk, component cgr fc->f[cS[i]][k][idx + off[2 * i] + off[2 * i + 1]]); else f[k] = 0; - fields[i] = IVEC_LOOP_WEIGHT(s0, s1, e0, e1, 1.0) * complex(f[0], f[1]) * ph[i]; + fields[i] = (data->snap ? 1.0 : IVEC_LOOP_WEIGHT(s0, s1, e0, e1, 1.0)) * complex(f[0], f[1]) * ph[i]; } } @@ -561,7 +562,7 @@ cdouble *collapse_array(cdouble *array, int *rank, size_t dims[3], direction dir /**********************************************************************/ void *fields::do_get_array_slice(const volume &where, std::vector components, field_function fun, field_rfunction rfun, void *fun_data, - void *vslice, double frequency) { + void *vslice, double frequency, bool snap) { am_now_working_on(FieldOutput); /***************************************************************/ @@ -573,7 +574,6 @@ void *fields::do_get_array_slice(const volume &where, std::vector com array_slice_data data; int rank = get_array_slice_dimensions(where, dims, dirs, false, 0, &data); size_t slice_size = data.slice_size; - bool complex_data = (rfun == 0); cdouble *zslice; double *slice; @@ -591,6 +591,7 @@ void *fields::do_get_array_slice(const volume &where, std::vector com } data.vslice = vslice_uncollapsed; + data.snap = snap; data.fun = fun; data.rfun = rfun; data.fun_data = fun_data; @@ -674,40 +675,42 @@ void *fields::do_get_array_slice(const volume &where, std::vector com /***************************************************************/ double *fields::get_array_slice(const volume &where, std::vector components, field_rfunction rfun, void *fun_data, double *slice, - double frequency) { + double frequency, bool snap) { return (double *)do_get_array_slice(where, components, 0, rfun, fun_data, (void *)slice, - frequency); + frequency, snap); } cdouble *fields::get_complex_array_slice(const volume &where, std::vector components, field_function fun, void *fun_data, cdouble *slice, - double frequency) { + double frequency, bool snap) { return (cdouble *)do_get_array_slice(where, components, fun, 0, fun_data, (void *)slice, - frequency); + frequency, snap); } -double *fields::get_array_slice(const volume &where, component c, double *slice, double frequency) { +double *fields::get_array_slice(const volume &where, component c, double *slice, double frequency, + bool snap) { std::vector components(1); components[0] = c; return (double *)do_get_array_slice(where, components, 0, default_field_rfunc, 0, (void *)slice, - frequency); + frequency, snap); } double *fields::get_array_slice(const volume &where, derived_component c, double *slice, - double frequency) { + double frequency, bool snap) { int nfields; component carray[12]; field_rfunction rfun = derived_component_func(c, gv, nfields, carray); std::vector cs(carray, carray + nfields); - return (double *)do_get_array_slice(where, cs, 0, rfun, &nfields, (void *)slice, frequency); + return (double *)do_get_array_slice(where, cs, 0, rfun, &nfields, (void *)slice, + frequency, snap); } cdouble *fields::get_complex_array_slice(const volume &where, component c, cdouble *slice, - double frequency) { + double frequency, bool snap) { std::vector components(1); components[0] = c; return (cdouble *)do_get_array_slice(where, components, default_field_func, 0, 0, (void *)slice, - frequency); + frequency, snap); } cdouble *fields::get_source_slice(const volume &where, component source_slice_component, diff --git a/src/meep.hpp b/src/meep.hpp index f51bad148..cf9e54349 100644 --- a/src/meep.hpp +++ b/src/meep.hpp @@ -1658,24 +1658,27 @@ class fields { // must eventually be caller-deallocated via delete[]. double *get_array_slice(const volume &where, std::vector components, field_rfunction rfun, void *fun_data, double *slice = 0, - double frequency = 0); + double frequency = 0, + bool snap = false); std::complex *get_complex_array_slice(const volume &where, std::vector components, field_function fun, void *fun_data, std::complex *slice = 0, - double frequency = 0); + double frequency = 0, + bool snap = false); // alternative entry points for when you have no field // function, i.e. you want just a single component or // derived component.) double *get_array_slice(const volume &where, component c, double *slice = 0, - double frequency = 0); + double frequency = 0, bool snap = false); double *get_array_slice(const volume &where, derived_component c, double *slice = 0, - double frequency = 0); + double frequency = 0, bool snap = false); std::complex *get_complex_array_slice(const volume &where, component c, std::complex *slice = 0, - double frequency = 0); + double frequency = 0, + bool snap = false); // like get_array_slice, but for *sources* instead of fields std::complex *get_source_slice(const volume &where, component source_slice_component, @@ -1684,7 +1687,7 @@ class fields { // master routine for all above entry points void *do_get_array_slice(const volume &where, std::vector components, field_function fun, field_rfunction rfun, void *fun_data, void *vslice, - double frequency = 0); + double frequency = 0, bool snap = false); /* fetch and return coordinates and integration weights of grid points covered by an array slice, */ /* packed into a vector with format [NX, xtics[:], NY, ytics[:], NZ, ztics[:], weights[:] ] */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 6a9964d60..53eae02ae 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -112,7 +112,7 @@ TESTS = aniso_disp bench bragg_transmission convergence_cyl_waveguide cylindrica if WITH_MPI LOG_COMPILER = $(RUNCODE) else - TESTS += cyl-ellipsoid-ll + TESTS += cyl-ellipsoid-ll array-slice-ll endif # Note: this requires GNU make diff --git a/tests/array-slice-ll-ref.h5 b/tests/array-slice-ll-ref.h5 index 9d359db83c4e00f0f26c222cc99daff40af22f63..c54e9c945a0438157e822e0d91ce0f91332f5084 100644 GIT binary patch delta 53 zcmaEGn(4u5rVVSDS*9|-iQl||IfMz!n!JIzVX^|V(BxTcUF;w!28N7{8%-HECvY^( F1pra=6tMsR delta 53 zcmaEGn(4u5rVVSDSvF2S8@YJ{a|jcdHF*Pb!(;_!p~