diff --git a/doc/docs/Python_User_Interface.md b/doc/docs/Python_User_Interface.md
index 581dd3382..811be2601 100644
--- a/doc/docs/Python_User_Interface.md
+++ b/doc/docs/Python_User_Interface.md
@@ -3602,7 +3602,9 @@ current simulation time.
+ `cmplx`: `boolean`; if `True`, return complex-valued data otherwise return
real-valued data (default).
-+ `arr`: optional field to pass a pre-allocated NumPy array of the correct size,
++ `arr`: optional parameter to pass a pre-allocated NumPy array of the correct size and
+ type (either `numpy.float32` or `numpy.float64` depending on the [floating-point precision
+ of the fields and materials](Build_From_Source.md#floating-point-precision-of-the-fields-and-materials-arrays))
which will be overwritten with the field/material data instead of allocating a
new array. Normally, this will be the array returned from a previous call to
`get_array` for a similar slice, allowing one to re-use `arr` (e.g., when
@@ -3655,7 +3657,8 @@ def get_dft_array(self, dft_obj, component, num_freq):
-Returns the Fourier-transformed fields as a NumPy array.
+Returns the Fourier-transformed fields as a NumPy array. The type is either `numpy.complex64`
+or `numpy.complex128` depending on the [floating-point precision of the fields](Build_From_Source.md#floating-point-precision-of-the-fields-and-materials-arrays).
**Parameters:**
diff --git a/python/adjoint/optimization_problem.py b/python/adjoint/optimization_problem.py
index 2fb45d5ca..bce235748 100644
--- a/python/adjoint/optimization_problem.py
+++ b/python/adjoint/optimization_problem.py
@@ -248,7 +248,7 @@ def adjoint_run(self):
# Store adjoint fields for each design set of design variables
self.D_a.append(utils.gather_design_region_fields(self.sim,self.design_region_monitors,self.frequencies))
-
+
# reset the m number
if utils._check_if_cylindrical(self.sim):
self.sim.m = -self.sim.m
diff --git a/python/adjoint/utils.py b/python/adjoint/utils.py
index 04b041fe7..38ffbd8f9 100644
--- a/python/adjoint/utils.py
+++ b/python/adjoint/utils.py
@@ -37,14 +37,14 @@ def __init__(
def update_design_parameters(self, design_parameters):
self.design_parameters.update_weights(design_parameters)
-
+
def update_beta(self,beta):
self.design_parameters.beta=beta
def get_gradient(self, sim, fields_a, fields_f, frequencies, finite_difference_step):
num_freqs = onp.array(frequencies).size
shapes = []
- '''We have the option to linear scale the gradients up front
+ '''We have the option to linearly scale the gradients up front
using the scalegrad parameter (leftover from MPB API). Not
currently needed for any existing feature (but available for
future use)'''
@@ -54,16 +54,18 @@ def get_gradient(self, sim, fields_a, fields_f, frequencies, finite_difference_s
returns a singleton element for the forward and adjoint fields.
This only occurs when we are in 2D and only working with a particular
polarization (as the other fields are never stored). For example, the
- 2D in-plane polarization consists of a single scalar Ez field
+ 2D in-plane polarization consists of a single scalar Ez field
(technically, meep doesn't store anything for these cases, but get_dft_array
still returns 0).
-
- Our get_gradient algorithm, however, requires we pass an array of
+
+ Our get_gradient algorithm, however, requires we pass an array of
zeros with the proper shape as the design_region.'''
spatial_shape = sim.get_array_slice_dimensions(component, vol=self.volume)[0]
if (fields_a[component_idx][0,...].size == 1):
- fields_a[component_idx] = onp.zeros(onp.insert(spatial_shape,0,num_freqs))
- fields_f[component_idx] = onp.zeros(onp.insert(spatial_shape,0,num_freqs))
+ fields_a[component_idx] = onp.zeros(onp.insert(spatial_shape,0,num_freqs),
+ dtype=onp.float32 if mp.is_single_precision() else onp.float64)
+ fields_f[component_idx] = onp.zeros(onp.insert(spatial_shape,0,num_freqs),
+ dtype=onp.float32 if mp.is_single_precision() else onp.float64)
if _check_if_cylindrical(sim):
'''For some reason, get_dft_array returns the field
components in a different order than the convention used
@@ -78,15 +80,16 @@ def get_gradient(self, sim, fields_a, fields_f, frequencies, finite_difference_s
shapes = onp.asarray(shapes).flatten(order='C')
fields_a = onp.concatenate(fields_a)
fields_f = onp.concatenate(fields_f)
-
+
grad = onp.zeros((num_freqs, self.num_design_params)) # preallocate
geom_list = sim.geometry
f = sim.fields
vol = sim._fit_volume_to_simulation(self.volume)
-
+
# compute the gradient
mp._get_gradient(grad,scalegrad,fields_a,fields_f,
- sim.gv,vol.swigobj,onp.array(frequencies),sim.geps,shapes,finite_difference_step)
+ sim.gv,vol.swigobj,onp.array(frequencies),
+ sim.geps,shapes,finite_difference_step)
return onp.squeeze(grad).T
def _check_if_cylindrical(sim):
@@ -203,7 +206,7 @@ def gather_design_region_fields(
fairly awkward to inspect directly. Their primary use case is supporting
gradient calculations.
"""
- fwd_fields = []
+ design_region_fields = []
for monitor in design_region_monitors:
fields_by_component = []
for component in _compute_components(simulation):
@@ -212,8 +215,8 @@ def gather_design_region_fields(
fields = simulation.get_dft_array(monitor, component, freq_idx)
fields_by_freq.append(_make_at_least_nd(fields))
fields_by_component.append(onp.stack(fields_by_freq))
- fwd_fields.append(fields_by_component)
- return fwd_fields
+ design_region_fields.append(fields_by_component)
+ return design_region_fields
def validate_and_update_design(
@@ -258,7 +261,7 @@ def create_adjoint_sources(
monitors: Iterable[ObjectiveQuantity],
monitor_values_grad: onp.ndarray) -> List[mp.Source]:
monitor_values_grad = onp.asarray(monitor_values_grad,
- dtype=onp.complex128)
+ dtype=onp.complex64 if mp.is_single_precision() else onp.complex128)
if not onp.any(monitor_values_grad):
raise RuntimeError(
'The gradient of all monitor values is zero, which '
@@ -273,7 +276,7 @@ def create_adjoint_sources(
for monitor_idx, monitor in enumerate(monitors):
# `dj` for each monitor will have a shape of (num frequencies,)
dj = onp.asarray(monitor_values_grad[monitor_idx],
- dtype=onp.complex128)
+ dtype=onp.complex64 if mp.is_single_precision() else onp.complex128)
if onp.any(dj):
adjoint_sources += monitor.place_adjoint_source(dj)
assert adjoint_sources
diff --git a/python/adjoint/wrapper.py b/python/adjoint/wrapper.py
index be793573f..3fad98c10 100644
--- a/python/adjoint/wrapper.py
+++ b/python/adjoint/wrapper.py
@@ -229,7 +229,9 @@ def _simulate_fwd(design_variables):
def _simulate_rev(res, monitor_values_grad):
"""Runs adjoint simulation, returning VJP of design wrt monitor values."""
fwd_fields = jax.tree_map(
- lambda x: onp.asarray(x, dtype=onp.complex128), res[0])
+ lambda x: onp.asarray(x,
+ dtype=onp.complex64 if mp.is_single_precision() else onp.complex128),
+ res[0])
design_variable_shapes = res[1]
adj_fields = self._run_adjoint_simulation(monitor_values_grad)
vjps = self._calculate_vjps(fwd_fields, adj_fields,
diff --git a/python/meep.i b/python/meep.i
index f1dc8012b..bb7f1c80c 100644
--- a/python/meep.i
+++ b/python/meep.i
@@ -150,7 +150,7 @@ static std::complex py_amp_func_wrap(const meep::vec &v) {
return ret;
}
-static std::complex py_field_func_wrap(const std::complex *fields,
+static std::complex py_field_func_wrap(const std::complex *fields,
const meep::vec &loc,
void *data_) {
SWIG_PYTHON_THREAD_SCOPED_BLOCK;
@@ -441,25 +441,25 @@ PyObject *_get_dft_array(meep::fields *f, dft_type dft, meep::component c, int n
// Return value: New reference
int rank;
size_t dims[3];
- std::complex *dft_arr = f->get_dft_array(dft, c, num_freq, &rank, dims);
+ std::complex *dft_arr = f->get_dft_array(dft, c, num_freq, &rank, dims);
- if (dft_arr==NULL){ // this can happen e.g. if component c vanishes by symmetry
- std::complex d[1] = {std::complex(0,0)};
- return PyArray_SimpleNewFromData(0, 0, NPY_CDOUBLE, d);
+ if (dft_arr == NULL) { // this can happen e.g. if component c vanishes by symmetry
+ std::complex d[1] = {std::complex(0,0)};
+ return PyArray_SimpleNewFromData(0, 0, sizeof(meep::realnum) == sizeof(float) ? NPY_CFLOAT : NPY_CDOUBLE, d);
}
if (rank == 0) // singleton results
- return PyArray_SimpleNewFromData(0, 0, NPY_CDOUBLE, dft_arr);
+ return PyArray_SimpleNewFromData(0, 0, sizeof(meep::realnum) == sizeof(float) ? NPY_CFLOAT : NPY_CDOUBLE, dft_arr);
size_t length = 1;
npy_intp *arr_dims = new npy_intp[rank];
for (int i = 0; i < rank; ++i) {
- arr_dims[i] = dims[i]; // implicit size_t -> int cast, presumed safe for individual array dimensions
- length *= dims[i];
+ arr_dims[i] = dims[i]; // implicit size_t -> int cast, presumed safe for individual array dimensions
+ length *= dims[i];
}
- PyObject *py_arr = PyArray_SimpleNew(rank, arr_dims, NPY_CDOUBLE);
- memcpy(PyArray_DATA((PyArrayObject*)py_arr), dft_arr, sizeof(std::complex) * length);
+ PyObject *py_arr = PyArray_SimpleNew(rank, arr_dims, sizeof(meep::realnum) == sizeof(float) ? NPY_CFLOAT : NPY_CDOUBLE);
+ memcpy(PyArray_DATA((PyArrayObject*)py_arr), dft_arr, sizeof(std::complex) * length);
delete[] dft_arr;
if (arr_dims) delete[] arr_dims;
@@ -844,8 +844,8 @@ meep::volume_list *make_volume_list(const meep::volume &v, int c,
%inline %{
void _get_gradient(PyObject *grad, double scalegrad, PyObject *fields_a, PyObject *fields_f,
- meep::grid_volume *grid_volume, meep::volume *where, PyObject *frequencies,
- meep_geom::geom_epsilon *geps, PyObject *fields_shapes, double fd_step) {
+ meep::grid_volume *grid_volume, meep::volume *where, PyObject *frequencies,
+ meep_geom::geom_epsilon *geps, PyObject *fields_shapes, double fd_step) {
// clean the gradient array
PyArrayObject *pao_grad = (PyArrayObject *)grad;
if (!PyArray_Check(pao_grad)) meep::abort("grad parameter must be numpy array.");
@@ -859,14 +859,14 @@ void _get_gradient(PyObject *grad, double scalegrad, PyObject *fields_a, PyObjec
if (!PyArray_Check(pao_fields_a)) meep::abort("adjoint fields parameter must be numpy array.");
if (!PyArray_ISCARRAY(pao_fields_a)) meep::abort("Numpy adjoint fields array must be C-style contiguous.");
if (PyArray_NDIM(pao_fields_a) !=1) {meep::abort("Numpy adjoint fields array must have 1 dimension.");}
- std::complex *fields_a_c = (std::complex *)PyArray_DATA(pao_fields_a);
+ std::complex *fields_a_c = (std::complex *)PyArray_DATA(pao_fields_a);
// clean the forward fields array
PyArrayObject *pao_fields_f = (PyArrayObject *)fields_f;
if (!PyArray_Check(pao_fields_f)) meep::abort("forward fields parameter must be numpy array.");
if (!PyArray_ISCARRAY(pao_fields_f)) meep::abort("Numpy forward fields array must be C-style contiguous.");
if (PyArray_NDIM(pao_fields_f) !=1) {meep::abort("Numpy forward fields array must have 1 dimension.");}
- std::complex *fields_f_c = (std::complex *)PyArray_DATA(pao_fields_f);
+ std::complex *fields_f_c = (std::complex *)PyArray_DATA(pao_fields_f);
// clean shapes array
PyArrayObject *pao_fields_shapes = (PyArrayObject *)fields_shapes;
@@ -1025,20 +1025,20 @@ void _get_gradient(PyObject *grad, double scalegrad, PyObject *fields_a, PyObjec
$1 = (size_t *)array_data($input);
}
-%typecheck(SWIG_TYPECHECK_POINTER, fragment="NumPy_Fragments") double* slice {
+%typecheck(SWIG_TYPECHECK_POINTER, fragment="NumPy_Fragments") meep::realnum* slice {
$1 = is_array($input);
}
-%typemap(in, fragment="NumPy_Macros") double* slice {
- $1 = (double *)array_data($input);
+%typemap(in, fragment="NumPy_Macros") meep::realnum* slice {
+ $1 = (meep::realnum *)array_data($input);
}
-%typecheck(SWIG_TYPECHECK_POINTER, fragment="NumPy_Fragments") std::complex* slice {
+%typecheck(SWIG_TYPECHECK_POINTER, fragment="NumPy_Fragments") std::complex* slice {
$1 = is_array($input);
}
-%typemap(in) std::complex* slice {
- $1 = (std::complex *)array_data($input);
+%typemap(in) std::complex* slice {
+ $1 = (std::complex *)array_data($input);
}
%typecheck(SWIG_TYPECHECK_POINTER) meep::component {
diff --git a/python/simulation.py b/python/simulation.py
index 5fbf66155..b99dccf3b 100644
--- a/python/simulation.py
+++ b/python/simulation.py
@@ -3337,7 +3337,9 @@ def get_array(self, component=None, vol=None, center=None, size=None, cmplx=None
+ `cmplx`: `boolean`; if `True`, return complex-valued data otherwise return
real-valued data (default).
- + `arr`: optional field to pass a pre-allocated NumPy array of the correct size,
+ + `arr`: optional parameter to pass a pre-allocated NumPy array of the correct size and
+ type (either `numpy.float32` or `numpy.float64` depending on the [floating-point precision
+ of the fields and materials](Build_From_Source.md#floating-point-precision-of-the-fields-and-materials-arrays))
which will be overwritten with the field/material data instead of allocating a
new array. Normally, this will be the array returned from a previous call to
`get_array` for a similar slice, allowing one to re-use `arr` (e.g., when
@@ -3407,7 +3409,10 @@ def get_array(self, component=None, vol=None, center=None, size=None, cmplx=None
arr = np.require(arr, requirements=['C', 'W'])
else:
- arr = np.zeros(dims, dtype=np.complex128 if cmplx else np.float64)
+ if mp.is_single_precision():
+ arr = np.zeros(dims, dtype=np.complex64 if cmplx else np.float32)
+ else:
+ 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, snap)
@@ -3418,7 +3423,8 @@ def get_array(self, component=None, vol=None, center=None, size=None, cmplx=None
def get_dft_array(self, dft_obj, component, num_freq):
"""
- Returns the Fourier-transformed fields as a NumPy array.
+ Returns the Fourier-transformed fields as a NumPy array. The type is either `numpy.complex64`
+ or `numpy.complex128` depending on the [floating-point precision of the fields](Build_From_Source.md#floating-point-precision-of-the-fields-and-materials-arrays).
**Parameters:**
@@ -3464,7 +3470,7 @@ def get_source(self, component, vol=None, center=None, size=None):
dim_sizes = np.zeros(3, dtype=np.uintp)
mp._get_array_slice_dimensions(self.fields, v, dim_sizes, True, False)
dims = [s for s in dim_sizes if s != 0]
- arr = np.zeros(dims, dtype=np.complex128)
+ arr = np.zeros(dims, dtype=np.complex64 if mp.is_single_precision() else np.complex128)
self.fields.get_source_slice(v, component, arr)
return arr
diff --git a/python/tests/test_adjoint_jax.py b/python/tests/test_adjoint_jax.py
index 768d7ac82..17994a8fa 100644
--- a/python/tests/test_adjoint_jax.py
+++ b/python/tests/test_adjoint_jax.py
@@ -175,7 +175,8 @@ def test_design_region_monitor_helpers(self):
for value in design_region_fields[0]:
self.assertIsInstance(value, onp.ndarray)
self.assertEqual(value.ndim, 4) # dims: freq, x, y, pad
- self.assertEqual(value.dtype, onp.complex128)
+ self.assertEqual(value.dtype,
+ onp.complex64 if mp.is_single_precision() else onp.complex128)
class WrapperTest(ApproxComparisonTestCase):
diff --git a/python/tests/test_adjoint_solver.py b/python/tests/test_adjoint_solver.py
index dae6e80f9..1f4efa360 100644
--- a/python/tests/test_adjoint_solver.py
+++ b/python/tests/test_adjoint_solver.py
@@ -15,7 +15,8 @@
resolution = 30
silicon = mp.Medium(epsilon=12)
-sapphire = mp.Medium(epsilon_diag=(10.225,10.225,9.95),epsilon_offdiag=(-0.825,-0.55*np.sqrt(3/2),0.55*np.sqrt(3/2)))
+sapphire = mp.Medium(epsilon_diag=(10.225,10.225,9.95),
+ epsilon_offdiag=(-0.825,-0.55*np.sqrt(3/2),0.55*np.sqrt(3/2)))
sxy = 5.0
cell_size = mp.Vector3(sxy,sxy,0)
@@ -469,7 +470,7 @@ def test_complex_fields(self):
## compare objective results
print("Ez2 -- adjoint solver: {}, traditional simulation: {}".format(adjsol_obj,Ez2_unperturbed))
- self.assertClose(adjsol_obj,Ez2_unperturbed,epsilon=1e-8)
+ self.assertClose(adjsol_obj,Ez2_unperturbed,epsilon=1e-6)
## compute perturbed |Ez|^2
Ez2_perturbed = forward_simulation_complex_fields(p+dp, frequencies)
@@ -533,7 +534,7 @@ def test_offdiagonal(self):
adj_scale = (dp[None,:]@adjsol_grad).flatten()
fd_grad = S12_perturbed-S12_unperturbed
print("Directional derivative -- adjoint solver: {}, FD: {}".format(adj_scale,fd_grad))
- tol = 0.04
+ tol = 0.05 if mp.is_single_precision() else 0.04
self.assertClose(adj_scale,fd_grad,epsilon=tol)
if __name__ == '__main__':
unittest.main()
diff --git a/python/tests/test_cavity_arrayslice.py b/python/tests/test_cavity_arrayslice.py
index bbedbebe6..42f758b6f 100644
--- a/python/tests/test_cavity_arrayslice.py
+++ b/python/tests/test_cavity_arrayslice.py
@@ -70,7 +70,7 @@ def test_2d_slice(self):
def test_1d_slice_user_array(self):
self.sim.run(until_after_sources=0)
- arr = np.zeros(126, dtype=np.float64)
+ arr = np.zeros(126, dtype=np.float32 if mp.is_single_precision() else np.float64)
vol = mp.Volume(center=self.center_1d, size=self.size_1d)
self.sim.get_array(mp.Hz, vol, arr=arr)
tol = 1e-5 if mp.is_single_precision() else 1e-8
@@ -78,7 +78,7 @@ def test_1d_slice_user_array(self):
def test_2d_slice_user_array(self):
self.sim.run(until_after_sources=0)
- arr = np.zeros((126, 38), dtype=np.float64)
+ arr = np.zeros((126, 38), dtype=np.float32 if mp.is_single_precision() else np.float64)
vol = mp.Volume(center=self.center_2d, size=self.size_2d)
self.sim.get_array(mp.Hz, vol, arr=arr)
tol = 1e-5 if mp.is_single_precision() else 1e-8
@@ -106,14 +106,14 @@ def test_1d_complex_slice(self):
self.sim.run(until_after_sources=0)
vol = mp.Volume(center=self.center_1d, size=self.size_1d)
hl_slice1d = self.sim.get_array(mp.Hz, vol, cmplx=True)
- self.assertTrue(hl_slice1d.dtype == np.complex128)
+ self.assertTrue(hl_slice1d.dtype == np.complex64 if mp.is_single_precision() else np.complex128)
self.assertTrue(hl_slice1d.shape[0] == 126)
def test_2d_complex_slice(self):
self.sim.run(until_after_sources=0)
vol = mp.Volume(center=self.center_2d, size=self.size_2d)
hl_slice2d = self.sim.get_array(mp.Hz, vol, cmplx=True)
- self.assertTrue(hl_slice2d.dtype == np.complex128)
+ self.assertTrue(hl_slice2d.dtype == np.complex64 if mp.is_single_precision() else np.complex128)
self.assertTrue(hl_slice2d.shape[0] == 126 and hl_slice2d.shape[1] == 38)
diff --git a/scheme/meep.i b/scheme/meep.i
index b88885e5d..9c8929ba8 100644
--- a/scheme/meep.i
+++ b/scheme/meep.i
@@ -33,9 +33,9 @@ static inline std::complex my_complex_func2(double t, void *f) {
}
typedef struct { SCM func; int nf; } my_field_func_data;
-static inline std::complex my_field_func(const std::complex *fields,
- const meep::vec &loc,
- void *data_) {
+static inline std::complex my_field_func(const std::complex *fields,
+ const meep::vec &loc,
+ void *data_) {
my_field_func_data *data = (my_field_func_data *) data_;
int num_items = data->nf;
cnumber *items = new cnumber[num_items];
diff --git a/src/array_slice.cpp b/src/array_slice.cpp
index b9905c16f..cb7d7aff3 100644
--- a/src/array_slice.cpp
+++ b/src/array_slice.cpp
@@ -43,17 +43,17 @@ constexpr size_t ARRAY_TO_ALL_BUFSIZE = 1 << 16; // Use (64k * 8 bytes) of buffe
/* repeatedly call sum_to_all to consolidate all entries of */
/* an array on all cores. */
/* array: in/out ptr to the data */
-/* array_size: data size in multiples of sizeof(double) */
+/* array_size: data size in multiples of sizeof(realnum) */
/***************************************************************/
-double *array_to_all(double *array, size_t array_size) {
+realnum *array_to_all(realnum *array, size_t array_size) {
#ifdef HAVE_MPI
- double *buffer = new double[ARRAY_TO_ALL_BUFSIZE];
+ realnum *buffer = new realnum[ARRAY_TO_ALL_BUFSIZE];
ptrdiff_t offset = 0;
size_t remaining = array_size;
while (remaining != 0) {
size_t xfer_size = (remaining > ARRAY_TO_ALL_BUFSIZE ? ARRAY_TO_ALL_BUFSIZE : remaining);
sum_to_all(array + offset, buffer, xfer_size);
- memcpy(array + offset, buffer, xfer_size * sizeof(double));
+ memcpy(array + offset, buffer, xfer_size * sizeof(realnum));
remaining -= xfer_size;
offset += xfer_size;
}
@@ -64,14 +64,22 @@ double *array_to_all(double *array, size_t array_size) {
return array;
}
-complex *array_to_all(complex *array, size_t array_size) {
- return (complex *)array_to_all((double *)array, 2 * array_size);
+complex *array_to_all(complex *array, size_t array_size) {
+ return (complex *)array_to_all((realnum *)array, 2 * array_size);
}
} // namespace
/***************************************************************************/
+std::complex cdouble(std::complex z) {
+ return std::complex(real(z), imag(z));
+}
+
+std::complex cdouble(std::complex z) {
+ return z;
+}
+
typedef struct {
// information related to the volume covered by the
@@ -101,7 +109,7 @@ typedef struct {
// temporary internal storage buffers
component *cS;
complex *ph;
- complex *fields;
+ complex *fields;
ptrdiff_t *offsets;
double frequency;
@@ -119,16 +127,16 @@ typedef struct {
} array_slice_data;
/* passthrough field function equivalent to component_fun in h5fields.cpp */
-static complex default_field_func(const complex *fields, const vec &loc, void *data_) {
+static complex default_field_func(const complex *fields, const vec &loc, void *data_) {
(void)loc; // unused
(void)data_; // unused
- return fields[0];
+ return cdouble(fields[0]);
}
-static double default_field_rfunc(const complex *fields, const vec &loc, void *data_) {
+static double default_field_rfunc(const complex *fields, const vec &loc, void *data_) {
(void)loc; // unused
(void)data_; // unused
- return real(fields[0]);
+ return real(cdouble(fields[0]));
}
/***************************************************************/
@@ -174,7 +182,7 @@ static void get_array_slice_dimensions_chunkloop(fields_chunk *fc, int ichnk, co
typedef struct {
component source_component;
ivec slice_imin, slice_imax;
- complex *slice;
+ complex *slice;
} source_slice_data;
bool in_range(int imin, int i, int imax) { return (imin <= i && i <= imax); }
@@ -310,18 +318,19 @@ static void get_array_slice_chunkloop(fields_chunk *fc, int ichnk, component cgr
// Otherwise proceed to compute the function of field components to be //
// tabulated on the slice, exactly as in fields::integrate. //
//-----------------------------------------------------------------------//
- double *slice = 0;
- complex *zslice = 0;
+ realnum *slice = 0;
+ complex *zslice = 0;
bool complex_data = (data->rfun == 0);
if (complex_data)
- zslice = (complex *)data->vslice;
+ zslice = (complex *)data->vslice;
else
- slice = (double *)data->vslice;
+ slice = (realnum *)data->vslice;
ptrdiff_t *off = data->offsets;
component *cS = data->cS;
double frequency = data->frequency;
- complex *fields = data->fields, *ph = data->ph;
+ complex *fields = data->fields;
+ complex *ph = data->ph;
const component *iecs = data->inveps_cs;
const direction *ieds = data->inveps_ds;
ptrdiff_t ieos[6];
@@ -515,8 +524,8 @@ bool increment(size_t *n, size_t *nMax, int rank) {
}
// data_size = 1,2 for real,complex-valued array
-double *collapse_array(double *array, int *rank, size_t dims[3], direction dirs[3], volume where,
- int data_size = 1) {
+realnum *collapse_array(realnum *array, int *rank, size_t dims[3], direction dirs[3], volume where,
+ int data_size = 1) {
/*--------------------------------------------------------------*/
/*- detect empty dimensions and compute rank and strides for */
@@ -560,9 +569,9 @@ double *collapse_array(double *array, int *rank, size_t dims[3], direction dirs[
/*--------------------------------------------------------------*/
size_t reduced_grid_size = reduced_dims[0] * (reduced_rank == 2 ? reduced_dims[1] : 1);
size_t reduced_array_size = data_size * reduced_grid_size;
- double *reduced_array = new double[reduced_array_size];
+ realnum *reduced_array = new realnum[reduced_array_size];
if (!reduced_array) meep::abort("%s:%i: out of memory (%zu)", __FILE__, __LINE__, reduced_array_size);
- memset(reduced_array, 0, reduced_array_size * sizeof(double));
+ memset(reduced_array, 0, reduced_array_size * sizeof(realnum));
size_t n[3] = {0, 0, 0};
do {
@@ -581,9 +590,9 @@ double *collapse_array(double *array, int *rank, size_t dims[3], direction dirs[
return reduced_array;
}
-complex *collapse_array(complex *array, int *rank, size_t dims[3], direction dirs[3],
- volume where) {
- return (complex *)collapse_array((double *)array, rank, dims, dirs, where, 2);
+complex *collapse_array(complex *array, int *rank, size_t dims[3], direction dirs[3],
+ volume where) {
+ return (complex *)collapse_array((realnum *)array, rank, dims, dirs, where, 2);
}
/**********************************************************************/
@@ -607,7 +616,7 @@ void *fields::do_get_array_slice(const volume &where, std::vector com
int elem_size = complex_data ? 2 : 1;
void *vslice_uncollapsed;
- vslice_uncollapsed = memset(new double[slice_size * elem_size], 0, slice_size * elem_size * sizeof(double));
+ vslice_uncollapsed = memset(new realnum[slice_size * elem_size], 0, slice_size * elem_size * sizeof(realnum));
data.vslice = vslice_uncollapsed;
data.snap = snap;
@@ -619,7 +628,7 @@ void *fields::do_get_array_slice(const volume &where, std::vector com
int num_components = components.size();
data.cS = new component[num_components];
data.ph = new complex[num_components];
- data.fields = new complex[num_components];
+ data.fields = new complex[num_components];
data.offsets = new ptrdiff_t[2 * num_components];
memset(data.offsets, 0, 2 * num_components * sizeof(ptrdiff_t));
data.empty_dim[0] = data.empty_dim[1] = data.empty_dim[2] = data.empty_dim[3] =
@@ -659,19 +668,19 @@ void *fields::do_get_array_slice(const volume &where, std::vector com
loop_in_chunks(get_array_slice_chunkloop, (void *)&data, where, Centered, true, snap);
if (!snap) {
- double *slice = collapse_array((double *)vslice_uncollapsed, &rank, dims, dirs, where, elem_size);
+ realnum *slice = collapse_array((realnum *)vslice_uncollapsed, &rank, dims, dirs, where, elem_size);
rank = get_array_slice_dimensions(where, dims, dirs, true, false, 0, &data);
slice_size = data.slice_size;
- vslice_uncollapsed = (double*) slice;
+ vslice_uncollapsed = (realnum*) slice;
}
if (vslice) {
- memcpy(vslice, vslice_uncollapsed, slice_size * elem_size * sizeof(double));
- delete[] (double*) vslice_uncollapsed;
+ memcpy(vslice, vslice_uncollapsed, slice_size * elem_size * sizeof(realnum));
+ delete[] (realnum*) vslice_uncollapsed;
}
else
vslice = vslice_uncollapsed;
- array_to_all((double *)vslice, elem_size * slice_size);
+ array_to_all((realnum *)vslice, elem_size * slice_size);
delete[] data.offsets;
delete[] data.fields;
@@ -685,48 +694,48 @@ void *fields::do_get_array_slice(const volume &where, std::vector com
/***************************************************************/
/* entry points to get_array_slice */
/***************************************************************/
-double *fields::get_array_slice(const volume &where, std::vector components,
- field_rfunction rfun, void *fun_data, double *slice,
- double frequency, bool snap) {
- return (double *)do_get_array_slice(where, components, 0, rfun, fun_data, (void *)slice,
- frequency, snap);
+realnum *fields::get_array_slice(const volume &where, std::vector components,
+ field_rfunction rfun, void *fun_data, realnum *slice,
+ double frequency, bool snap) {
+ return (realnum *)do_get_array_slice(where, components, 0, rfun, fun_data, (void *)slice,
+ frequency, snap);
}
-complex *fields::get_complex_array_slice(const volume &where, std::vector components,
- field_function fun, void *fun_data, complex *slice,
- double frequency, bool snap) {
- return (complex *)do_get_array_slice(where, components, fun, 0, fun_data, (void *)slice,
- frequency, snap);
+complex *fields::get_complex_array_slice(const volume &where, std::vector components,
+ field_function fun, void *fun_data, complex *slice,
+ double frequency, bool snap) {
+ return (complex *)do_get_array_slice(where, components, fun, 0, fun_data, (void *)slice,
+ frequency, snap);
}
-double *fields::get_array_slice(const volume &where, component c, double *slice, double frequency,
- bool snap) {
+realnum *fields::get_array_slice(const volume &where, component c, realnum *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, snap);
+ return (realnum *)do_get_array_slice(where, components, 0, default_field_rfunc, 0, (void *)slice,
+ frequency, snap);
}
-double *fields::get_array_slice(const volume &where, derived_component c, double *slice,
- double frequency, bool snap) {
+realnum *fields::get_array_slice(const volume &where, derived_component c, realnum *slice,
+ 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, snap);
+ return (realnum *)do_get_array_slice(where, cs, 0, rfun, &nfields, (void *)slice,
+ frequency, snap);
}
-complex *fields::get_complex_array_slice(const volume &where, component c, complex *slice,
- double frequency, bool snap) {
+complex *fields::get_complex_array_slice(const volume &where, component c, complex *slice,
+ double frequency, bool snap) {
std::vector components(1);
components[0] = c;
- return (complex *)do_get_array_slice(where, components, default_field_func, 0, 0, (void *)slice,
- frequency, snap);
+ return (complex *)do_get_array_slice(where, components, default_field_func, 0, 0, (void *)slice,
+ frequency, snap);
}
-complex *fields::get_source_slice(const volume &where, component source_slice_component,
- complex *slice) {
+complex *fields::get_source_slice(const volume &where, component source_slice_component,
+ complex *slice) {
size_t dims[3];
direction dirs[3];
vec min_max_loc[2];
@@ -737,18 +746,18 @@ complex *fields::get_source_slice(const volume &where, component source_
data.source_component = source_slice_component;
data.slice_imin = gv.round_vec(min_max_loc[0]);
data.slice_imax = gv.round_vec(min_max_loc[1]);
- data.slice = new complex[slice_size];
+ data.slice = new complex[slice_size];
if (!data.slice) meep::abort("%s:%i: out of memory (%zu)", __FILE__, __LINE__, slice_size);
loop_in_chunks(get_source_slice_chunkloop, (void *)&data, where, Centered, true, false);
- complex *slice_collapsed = collapse_array(data.slice, &rank, dims, dirs, where);
+ complex *slice_collapsed = collapse_array(data.slice, &rank, dims, dirs, where);
rank = get_array_slice_dimensions(where, dims, dirs, true, false);
slice_size = dims[0] * (rank >= 2 ? dims[1] : 1) * (rank == 3 ? dims[2] : 1);
if (slice) {
- memcpy(slice, slice_collapsed, 2 * slice_size * sizeof(double));
- delete[] (complex*) slice_collapsed;
+ memcpy(slice, slice_collapsed, 2 * slice_size * sizeof(realnum));
+ delete[] (complex*) slice_collapsed;
}
else
slice = slice_collapsed;
@@ -769,7 +778,7 @@ std::vector fields::get_array_metadata(const volume &where) {
vec min_max_loc[2]; // extremal points in subgrid
get_array_slice_dimensions(where, dims, dirs, true, false, min_max_loc);
- double *weights = get_array_slice(where, NO_COMPONENT);
+ realnum *weights = get_array_slice(where, NO_COMPONENT);
/* get length and endpoints of x,y,z tics arrays */
size_t nxyz[3] = {1, 1, 1};
diff --git a/src/dft.cpp b/src/dft.cpp
index cb6cd13ad..f97bbe730 100644
--- a/src/dft.cpp
+++ b/src/dft.cpp
@@ -860,8 +860,8 @@ dft_fields fields::add_dft_fields(component *components, int num_components, con
/* chunk-level processing for fields::process_dft_component. */
/***************************************************************/
complex dft_chunk::process_dft_component(int rank, direction *ds, ivec min_corner, ivec max_corner,
- int num_freq, h5file *file, double *buffer, int reim,
- complex *field_array, void *mode1_data, void *mode2_data,
+ int num_freq, h5file *file, realnum *buffer, int reim,
+ complex *field_array, void *mode1_data, void *mode2_data,
int ic_conjugate, bool retain_interp_weights,
fields *parent) {
@@ -1026,7 +1026,7 @@ complex dft_chunk::process_dft_component(int rank, direction *ds, ivec m
/* are processed. */
/***************************************************************/
complex fields::process_dft_component(dft_chunk **chunklists, int num_chunklists, int num_freq,
- component c, const char *HDF5FileName, complex **pfield_array,
+ component c, const char *HDF5FileName, complex **pfield_array,
int *array_rank, size_t *array_dims, direction *array_dirs,
void *mode1_data, void *mode2_data, component c_conjugate,
bool *first_component, bool retain_interp_weights) {
@@ -1099,15 +1099,15 @@ complex fields::process_dft_component(dft_chunk **chunklists, int num_ch
/* buffer for process-local contributions to HDF5 output files,*/
/* like h5_output_data::buf in h5fields.cpp */
/***************************************************************/
- double *buffer = 0;
- complex *field_array = 0;
+ realnum *buffer = 0;
+ complex *field_array = 0;
int reim_max = 0;
if (HDF5FileName) {
- buffer = new double[bufsz];
+ buffer = new realnum[bufsz];
reim_max = 1;
}
else if (pfield_array)
- *pfield_array = field_array = (array_size ? new complex[array_size] : 0);
+ *pfield_array = field_array = (array_size ? new complex[array_size] : 0);
complex overlap = 0.0;
for (int reim = 0; reim <= reim_max; reim++) {
@@ -1118,7 +1118,7 @@ complex fields::process_dft_component(dft_chunk **chunklists, int num_ch
char dataname[100];
snprintf(dataname, 100, "%s_%i.%c", component_name(c), num_freq, reim ? 'i' : 'r');
file->create_or_extend_data(dataname, rank, dims, false /* append_data */,
- false /* single_precision */);
+ sizeof(realnum) == sizeof(float) /* single_precision */);
}
for (int ncl = 0; ncl < num_chunklists; ncl++)
@@ -1139,7 +1139,7 @@ complex fields::process_dft_component(dft_chunk **chunklists, int num_ch
/* on all cores */
/***************************************************************/
#define BUFSIZE 1 << 20 // use 1M element (16 MB) buffer
- complex *buf = new complex[BUFSIZE];
+ complex *buf = new complex[BUFSIZE];
ptrdiff_t offset = 0;
size_t remaining = array_size;
while (remaining != 0) {
@@ -1147,7 +1147,7 @@ complex fields::process_dft_component(dft_chunk **chunklists, int num_ch
am_now_working_on(MpiAllTime);
sum_to_all(field_array + offset, buf, size);
finished_working();
- memcpy(field_array + offset, buf, size * sizeof(complex));
+ memcpy(field_array + offset, buf, size * sizeof(complex));
remaining -= size;
offset += size;
}
@@ -1169,46 +1169,46 @@ complex fields::process_dft_component(dft_chunk **chunklists, int num_ch
/***************************************************************/
/* routines for fetching arrays of dft fields */
/***************************************************************/
-complex *collapse_array(complex *array, int *rank, size_t dims[3], direction dirs[3], volume where);
+complex *collapse_array(complex *array, int *rank, size_t dims[3], direction dirs[3], volume where);
-complex *fields::get_dft_array(dft_flux flux, component c, int num_freq, int *rank,
- size_t dims[3]) {
+complex *fields::get_dft_array(dft_flux flux, component c, int num_freq, int *rank,
+ size_t dims[3]) {
dft_chunk *chunklists[2];
chunklists[0] = flux.E;
chunklists[1] = flux.H;
- complex *array;
+ complex *array;
direction dirs[3];
process_dft_component(chunklists, 2, num_freq, c, 0, &array, rank, dims, dirs);
return collapse_array(array, rank, dims, dirs, flux.where);
}
-complex *fields::get_dft_array(dft_force force, component c, int num_freq, int *rank,
- size_t dims[3]) {
+complex *fields::get_dft_array(dft_force force, component c, int num_freq, int *rank,
+ size_t dims[3]) {
dft_chunk *chunklists[3];
chunklists[0] = force.offdiag1;
chunklists[1] = force.offdiag2;
chunklists[2] = force.diag;
- complex *array;
+ complex *array;
direction dirs[3];
process_dft_component(chunklists, 3, num_freq, c, 0, &array, rank, dims, dirs);
return collapse_array(array, rank, dims, dirs, force.where);
}
-complex *fields::get_dft_array(dft_near2far n2f, component c, int num_freq, int *rank,
- size_t dims[3]) {
+complex *fields::get_dft_array(dft_near2far n2f, component c, int num_freq, int *rank,
+ size_t dims[3]) {
dft_chunk *chunklists[1];
chunklists[0] = n2f.F;
- complex *array;
+ complex *array;
direction dirs[3];
process_dft_component(chunklists, 1, num_freq, c, 0, &array, rank, dims, dirs);
return collapse_array(array, rank, dims, dirs, n2f.where);
}
-complex *fields::get_dft_array(dft_fields fdft, component c, int num_freq, int *rank,
- size_t dims[3]) {
+complex *fields::get_dft_array(dft_fields fdft, component c, int num_freq, int *rank,
+ size_t dims[3]) {
dft_chunk *chunklists[1];
chunklists[0] = fdft.chunks;
- complex *array;
+ complex *array;
direction dirs[3];
process_dft_component(chunklists, 1, num_freq, c, 0, &array, rank, dims, dirs);
return collapse_array(array, rank, dims, dirs, fdft.where);
@@ -1255,7 +1255,7 @@ void fields::output_dft_components(dft_chunk **chunklists, int num_chunklists, v
0, Ex, &first_component);
}
else {
- complex *array = 0;
+ complex *array = 0;
int rank;
size_t dims[3];
direction dirs[3];
diff --git a/src/energy_and_flux.cpp b/src/energy_and_flux.cpp
index 4514e8553..889785d09 100644
--- a/src/energy_and_flux.cpp
+++ b/src/energy_and_flux.cpp
@@ -58,10 +58,10 @@ double fields::field_energy_in_box(const volume &where) {
return electric_energy_in_box(where) + cur_step_magnetic_energy;
}
-static complex dot_integrand(const complex *fields, const vec &loc, void *data_) {
+static complex dot_integrand(const complex *fields, const vec &loc, void *data_) {
(void)loc;
(void)data_; // unused;
- return real(conj(fields[0]) * fields[1]);
+ return real(conj(cdouble(fields[0])) * cdouble(fields[1]));
}
double fields::field_energy_in_box(component c, const volume &where) {
@@ -249,12 +249,13 @@ flux_vol *fields::add_flux_plane(const vec &p1, const vec &p2) {
is more expensive and requires us to know the boundary orientation, and
does not seem worth the trouble at this point. */
-static complex dot3_max_integrand(const complex *fields, const vec &loc,
+static complex dot3_max_integrand(const complex *fields, const vec &loc,
void *data_) {
(void)loc;
(void)data_; // unused;
- return (real(conj(fields[0]) * fields[3]) + real(conj(fields[1]) * fields[4]) +
- real(conj(fields[2]) * fields[5]));
+ return (real(conj(cdouble(fields[0])) * cdouble(fields[3])) +
+ real(conj(cdouble(fields[1])) * cdouble(fields[4])) +
+ real(conj(cdouble(fields[2])) * cdouble(fields[5])));
}
double fields::electric_energy_max_in_box(const volume &where) {
@@ -294,10 +295,10 @@ double fields::modal_volume_in_box(const volume &where) {
typedef double (*fx_func)(const vec &);
-static complex dot_fx_integrand(const complex *fields, const vec &loc,
+static complex dot_fx_integrand(const complex *fields, const vec &loc,
void *data_) {
fx_func fx = (fx_func)data_;
- return (real(conj(fields[0]) * fields[1]) * fx(loc));
+ return (real(conj(cdouble(fields[0])) * cdouble(fields[1])) * fx(loc));
}
/* computes integral of f(x) * |E|^2 / integral epsilon*|E|^2 */
diff --git a/src/h5fields.cpp b/src/h5fields.cpp
index 672b273d1..d7840f89d 100644
--- a/src/h5fields.cpp
+++ b/src/h5fields.cpp
@@ -48,7 +48,7 @@ typedef struct {
const component *components;
component *cS;
complex *ph;
- complex *fields;
+ complex *fields;
ptrdiff_t *offsets;
double frequency;
int ninveps;
@@ -143,7 +143,8 @@ static void h5_output_chunkloop(fields_chunk *fc, int ichnk, component cgrid, iv
ptrdiff_t *off = data->offsets;
component *cS = data->cS;
- complex *fields = data->fields, *ph = data->ph;
+ complex *fields = data->fields;
+ complex *ph = data->ph;
double frequency = data->frequency;
const component *iecs = data->inveps_cs;
const direction *ieds = data->inveps_ds;
@@ -267,7 +268,7 @@ void fields::output_hdf5(h5file *file, const char *dataname, int num_fields,
data.components = components;
data.cS = new component[num_fields];
data.ph = new complex[num_fields];
- data.fields = new complex[num_fields];
+ data.fields = new complex[num_fields];
data.fun = fun;
data.fun_data_ = fun_data_;
@@ -351,7 +352,7 @@ typedef struct {
void *fun_data_;
} rintegrand_data;
-static complex rintegrand_fun(const complex *fields, const vec &loc, void *data_) {
+static complex rintegrand_fun(const complex *fields, const vec &loc, void *data_) {
rintegrand_data *data = (rintegrand_data *)data_;
return data->fun(fields, loc, data->fun_data_);
}
@@ -374,10 +375,10 @@ void fields::output_hdf5(const char *dataname, int num_fields, const component *
/***************************************************************************/
-static complex component_fun(const complex *fields, const vec &loc, void *data_) {
+static complex component_fun(const complex *fields, const vec &loc, void *data_) {
(void)loc; // unused
(void)data_; // unused
- return fields[0];
+ return cdouble(fields[0]);
}
void fields::output_hdf5(component c, const volume &where, h5file *file, bool append_data,
diff --git a/src/integrate.cpp b/src/integrate.cpp
index 7445df910..c94a63e09 100644
--- a/src/integrate.cpp
+++ b/src/integrate.cpp
@@ -29,7 +29,7 @@ struct integrate_data {
const component *components;
component *cS;
complex *ph;
- complex *fvals;
+ complex *fvals;
ptrdiff_t *offsets;
int ninveps;
component inveps_cs[3];
@@ -37,7 +37,7 @@ struct integrate_data {
int ninvmu;
component invmu_cs[3];
direction invmu_ds[3];
- complex sum;
+ complex sum;
double maxabs;
field_function integrand;
void *integrand_data_;
@@ -51,7 +51,8 @@ static void integrate_chunkloop(fields_chunk *fc, int ichunk, component cgrid, i
integrate_data *data = (integrate_data *)data_;
ptrdiff_t *off = data->offsets;
component *cS = data->cS;
- complex *fvals = data->fvals, *ph = data->ph;
+ complex *fvals = data->fvals;
+ complex *ph = data->ph;
complex sum = 0.0;
double maxabs = 0;
const component *iecs = data->inveps_cs;
@@ -146,7 +147,7 @@ complex fields::integrate(int num_fvals, const component *components,
data.components = components;
data.cS = new component[num_fvals];
data.ph = new complex[num_fvals];
- data.fvals = new complex[num_fvals];
+ data.fvals = new complex[num_fvals];
data.sum = 0;
data.maxabs = 0;
data.integrand = integrand;
@@ -196,14 +197,15 @@ complex fields::integrate(int num_fvals, const component *components,
if (maxabs) *maxabs = max_to_all(data.maxabs);
data.sum = sum_to_all(data.sum);
- return complex(real(data.sum), imag(data.sum));
+ return cdouble(data.sum);
}
typedef struct {
field_rfunction integrand;
void *integrand_data;
} rfun_wrap_data;
-static complex rfun_wrap(const complex *fvals, const vec &loc, void *data_) {
+
+static complex rfun_wrap(const complex *fvals, const vec &loc, void *data_) {
rfun_wrap_data *data = (rfun_wrap_data *)data_;
return data->integrand(fvals, loc, data->integrand_data);
}
@@ -231,11 +233,11 @@ double fields::max_abs(int num_fvals, const component *components, field_rfuncti
return max_abs(num_fvals, components, rfun_wrap, &data, where);
}
-static complex return_the_field(const complex *fields, const vec &loc,
- void *integrand_data_) {
+static complex return_the_field(const complex *fields, const vec &loc,
+ void *integrand_data_) {
(void)integrand_data_;
(void)loc; // unused
- return fields[0];
+ return cdouble(fields[0]);
}
double fields::max_abs(int c, const volume &where) {
diff --git a/src/integrate2.cpp b/src/integrate2.cpp
index 48e255d74..f8671987c 100644
--- a/src/integrate2.cpp
+++ b/src/integrate2.cpp
@@ -35,7 +35,7 @@ struct integrate_data {
const component *components2;
component *cS;
complex *ph;
- complex *fvals;
+ complex *fvals;
ptrdiff_t *offsets;
int ninveps;
component inveps_cs[3];
@@ -43,7 +43,7 @@ struct integrate_data {
int ninvmu;
component invmu_cs[3];
direction invmu_ds[3];
- complex sum;
+ complex sum;
double maxabs;
field_function integrand;
void *integrand_data_;
@@ -57,7 +57,8 @@ static void integrate_chunkloop(fields_chunk *fc, int ichunk, component cgrid, i
integrate_data *data = (integrate_data *)data_;
ptrdiff_t *off = data->offsets;
component *cS = data->cS;
- complex *fvals = data->fvals, *ph = data->ph;
+ complex *fvals = data->fvals;
+ complex *ph = data->ph;
complex sum = 0.0;
double maxabs = 0;
const component *iecs = data->inveps_cs;
@@ -223,7 +224,7 @@ complex fields::integrate2(const fields &fields2, int num_fvals1,
data.components2 = components2;
data.cS = new component[num_fvals1 + num_fvals2];
data.ph = new complex[num_fvals1 + num_fvals2];
- data.fvals = new complex[num_fvals1 + num_fvals2];
+ data.fvals = new complex[num_fvals1 + num_fvals2];
data.sum = 0;
data.maxabs = 0;
data.integrand = integrand;
@@ -285,14 +286,15 @@ complex fields::integrate2(const fields &fields2, int num_fvals1,
if (maxabs) *maxabs = max_to_all(data.maxabs);
data.sum = sum_to_all(data.sum);
- return complex(real(data.sum), imag(data.sum));
+ return cdouble(data.sum);
}
typedef struct {
field_rfunction integrand;
void *integrand_data;
} rfun_wrap_data;
-static complex rfun_wrap(const complex *fields, const vec &loc, void *data_) {
+
+static complex rfun_wrap(const complex *fields, const vec &loc, void *data_) {
rfun_wrap_data *data = (rfun_wrap_data *)data_;
return data->integrand(fields, loc, data->integrand_data);
}
diff --git a/src/meep.hpp b/src/meep.hpp
index 488c517b9..6c15378a2 100644
--- a/src/meep.hpp
+++ b/src/meep.hpp
@@ -60,6 +60,10 @@ const double nan = NAN;
const double nan = -7.0415659787563146e103; // ideally, a value never encountered in practice
#endif
+// Defined in array_slice.cpp
+std::complex cdouble(std::complex z);
+std::complex cdouble(std::complex z);
+
class h5file;
// Defined in monitor.cpp
@@ -1126,8 +1130,8 @@ class dft_chunk {
// fields::process_dft_component
std::complex process_dft_component(int rank, direction *ds, ivec min_corner,
ivec max_corner, int num_freq, h5file *file,
- double *buffer, int reim,
- std::complex *field_array, void *mode1_data,
+ realnum *buffer, int reim,
+ std::complex *field_array, void *mode1_data,
void *mode2_data, int ic_conjugate,
bool retain_interp_weights, fields *parent);
@@ -1627,9 +1631,9 @@ typedef void (*field_chunkloop)(fields_chunk *fc, int ichunk, component cgrid, i
vec s0, vec s1, vec e0, vec e1, double dV0, double dV1, ivec shift,
std::complex shift_phase, const symmetry &S, int sn,
void *chunkloop_data);
-typedef std::complex (*field_function)(const std::complex *fields, const vec &loc,
+typedef std::complex (*field_function)(const std::complex *fields, const vec &loc,
void *integrand_data_);
-typedef double (*field_rfunction)(const std::complex *fields, const vec &loc,
+typedef double (*field_rfunction)(const std::complex *fields, const vec &loc,
void *integrand_data_);
field_rfunction derived_component_func(derived_component c, const grid_volume &gv, int &nfields,
@@ -1812,33 +1816,33 @@ class fields {
// of the correct size.
// otherwise, a new buffer is allocated and returned; it
// 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,
- 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,
- bool snap = false);
+ realnum *get_array_slice(const volume &where, std::vector components,
+ field_rfunction rfun, void *fun_data, realnum *slice = 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,
+ 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, bool snap = false);
- double *get_array_slice(const volume &where, derived_component c, double *slice = 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,
- bool snap = false);
+ realnum *get_array_slice(const volume &where, component c, realnum *slice = 0,
+ double frequency = 0, bool snap = false);
+ realnum *get_array_slice(const volume &where, derived_component c, realnum *slice = 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,
+ 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,
- std::complex *slice = 0);
+ std::complex *get_source_slice(const volume &where, component source_slice_component,
+ std::complex *slice = 0);
// master routine for all above entry points
void *do_get_array_slice(const volume &where, std::vector components,
@@ -2079,7 +2083,7 @@ class fields {
/********************************************************/
std::complex