Adding source volumes can be treated as a kind of "integration" problem, since we need to loop over all the chunks that intersect the source grid_volume, with appropriate interpolation weights at the boundaries so that the integral of the current is fixed regardless of resolution. Unlike most uses of fields::loop_in_chunks, however, we set use_symmetry=false: we only find the inter
| 241 | with the untransformed chunks (since the transformed versions are |
| 242 | implicit). */ |
| 243 | static void src_vol_chunkloop(fields_chunk *fc, int ichunk, component c, ivec is, ivec ie, vec s0, |
| 244 | vec s1, vec e0, vec e1, double dV0, double dV1, ivec shift, |
| 245 | complex<double> shift_phase, const symmetry &S, int sn, void *data_) { |
| 246 | src_vol_chunkloop_data *data = (src_vol_chunkloop_data *)data_; |
| 247 | |
| 248 | (void)S; |
| 249 | (void)sn; // these should be the identity |
| 250 | (void)dV0; |
| 251 | (void)dV1; // grid_volume weighting is included in data->amp |
| 252 | (void)ichunk; |
| 253 | |
| 254 | size_t npts = 1; |
| 255 | LOOP_OVER_DIRECTIONS(is.dim, d) { npts *= (ie.in_direction(d) - is.in_direction(d)) / 2 + 1; } |
| 256 | std::vector<ptrdiff_t> index_array(npts); |
| 257 | std::vector<complex<double> > amps_array(npts); |
| 258 | |
| 259 | complex<double> amp = data->amp * conj(shift_phase); |
| 260 | |
| 261 | direction cd = component_direction(c); |
| 262 | |
| 263 | double inva = fc->gv.inva; |
| 264 | size_t idx_vol = 0; |
| 265 | LOOP_OVER_IVECS(fc->gv, is, ie, idx) { |
| 266 | IVEC_LOOP_ILOC(fc->gv, iloc); |
| 267 | if (!fc->gv.owns(iloc)) continue; |
| 268 | |
| 269 | IVEC_LOOP_LOC(fc->gv, loc); |
| 270 | loc += shift * (0.5 * inva); |
| 271 | |
| 272 | vec rel_loc = loc - data->center; |
| 273 | amps_array[idx_vol] = IVEC_LOOP_WEIGHT(s0, s1, e0, e1, 1) * amp * data->A(rel_loc); |
| 274 | |
| 275 | // check for invalid sources at r=0 in cylindrical coordinates |
| 276 | if (fc->gv.dim == Dcyl && loc.r() == 0 && amps_array[idx_vol] != 0.0) { |
| 277 | if (fc->m == 0) { |
| 278 | if (component_direction(c) == R || component_direction(c) == P) |
| 279 | meep::abort("Not possible to place a %s source at r=0 in " |
| 280 | "cylindrical coordinates for m = 0.", |
| 281 | component_name(c)); |
| 282 | } |
| 283 | else if (fabs(fc->m) == 1.0) { |
| 284 | if (component_direction(c) == Z) |
| 285 | meep::abort("Not possible to place a %s source at r=0 in " |
| 286 | "cylindrical coordinates for |m| = 1.0.", |
| 287 | component_name(c)); |
| 288 | } |
| 289 | else { |
| 290 | meep::abort("Not possible to place a source at r=0 in " |
| 291 | "cylindrical coordinates for m = %g.", |
| 292 | fc->m); |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | /* for "D" sources, multiply by epsilon. FIXME: this is not quite |
| 297 | right because it doesn't handle non-diagonal chi1inv! |
| 298 | similarly, for "B" sources, multiply by mu. */ |
| 299 | if (is_D(c) && fc->s->chi1inv[c - Dx + Ex][cd]) |
| 300 | amps_array[idx_vol] /= fc->s->chi1inv[c - Dx + Ex][cd][idx]; |
nothing calls this directly
no test coverage detected