TDMS
Time Domain Maxwell Solver
All Classes Namespaces Files Functions Variables Typedefs Enumerations Macros Pages
field.h
Go to the documentation of this file.
1/**
2 * @file field.h
3 * @brief Classes for the electric and magnetic (split) fields on a grid.
4 */
5#pragma once
6
7#include <complex>
8
9#include "arrays.h"
10#include "arrays/eh_vec.h"
11#include "arrays/tensor3d.h"
12#include "cell_coordinate.h"
13#include "dimensions.h"
14#include "input_flags.h"
15#include "mat_io.h"
17
18/**
19 * A generic grid entity. For example:
20 *
21 * ______________________ (2, 1, 0)
22 * / / /
23 * / / /
24 * /___________/_________/
25 * (0, 0, 0) (1, 0, 0) (2, 0, 0)
26 *
27 * has I_tot = 2, J_tot = 1, K_tot = 0.
28 *
29 * NOTE: For storage purposes, this means that field values associated to cells
30 * are stored _to the left_. That is, Grid(0,0,0) is associated to the cell
31 * (-1,-1,-1). This is contrary to the way values are associated to cells, where
32 * cell (0,0,0) is associated to the field values (0,0,0).
33 */
34class Grid {
35protected:
36 // the preferred interpolation methods (interpolation_method) for
37 // interpolating between the grid values, default is Cubic
38 tdms_flags::InterpolationMethod interpolation_method =
39 tdms_flags::InterpolationMethod::Cubic;
40
41public:
42 // The {IJK}_tot values of this grid
43 IJKDimensions tot = {0, 0, 0};
44
45 /**
46 * Maximum value out of I_tot, J_tot and K_tot
47 * @return value
48 */
49 int max_IJK_tot() const { return tot.max(); };
50
51 /**
52 * @brief Set the preferred interpolation methods
53 */
55 interpolation_method = im;
56 };
57};
58
59class SplitFieldComponent : public Tensor3D<double> {
60public:
61 int n_threads = 1;// Number of threads this component was chunked with
62 fftw_plan *plan_f = nullptr;// Forward fftw plan
63 fftw_plan *plan_b = nullptr;// Backward fftw plan
64
65 void initialise_from_matlab(double ***tensor, Dimensions &dims);
66
67 /**
68 * Initialise a vector of 1d discrete Fourier transform plans
69 * @param n_threads Number of threads that will be used
70 * @param size Length of the vector
71 * @param eh_vec TODO: what is this?
72 */
73 void initialise_fftw_plan(int n_threads, int size, EHVec &eh_vec);
74
76};
77
78/**
79 * @brief A split field defined over a grid.
80 *
81 * To reconstruct the components we have e.g.: Ex = Exy + Exz multiplied by a
82 * phase factor
83 */
84class SplitField : public Grid {
85protected:
86 virtual int delta_n() = 0;// TODO: no idea what this is or why it's needed
87
88public:
89 /*! Magnitude of the xy component at each grid point (i,j,k) */
91 /*! Magnitude of the xz component at each grid point (i,j,k) */
93 /*! Magnitude of the yx component at each grid point (i,j,k) */
95 /*! Magnitude of the yz component at each grid point (i,j,k) */
97 /*! Magnitude of the zx component at each grid point (i,j,k) */
99 /*! Magnitude of the zy component at each grid point (i,j,k) */
101
102 /**
103 * Default no arguments constructor
104 */
105 SplitField() = default;
106
107 /**
108 * Constructor of the field with a defined size in the x, y, z Cartesian
109 * dimensions
110 */
111 SplitField(int I_total, int J_total, int K_total);
112
113 /**
114 * Allocate the memory appropriate for all the 3D tensors associated with
115 * this split field
116 */
117 void allocate();
118
119 /**
120 * Set all the values of all components of the field to zero
121 */
122 void zero();
123
124 /**
125 * Allocate and set to zero all components of the field
126 */
128 allocate();
129 zero();
130 }
131
132 /**
133 * Initialise the fftw plans for all components
134 * @param n_threads Number of threads to split over
135 * @param eh_vec // TODO
136 */
137 void initialise_fftw_plan(int n_threads, EHVec &eh_vec);
138
139 /**
140 * @brief Fetches the largest absolute value of the field.
141 *
142 * Split field values are sums of the corresponding components, so this
143 * function returns the largest absolute value of the entries in (xy + xz),
144 * (yx + yz), (zx + zy)
145 *
146 * @return double Largest (by absolute value) field value
147 */
149
150 /**
151 * @brief Interpolates a SplitField component to the centre of a Yee cell
152 *
153 * @param d SplitField component to interpolate
154 * @param cell Index (i,j,k) of the Yee cell to interpolate to the centre of
155 * @return double The interpolated field value
156 */
157 virtual double interpolate_to_centre_of(AxialDirection d,
158 CellCoordinate cell) = 0;
159};
160
162protected:
163 int delta_n() override {
164 return -1;
165 };// TODO: no idea what this is or why it's needed
166
167public:
168 ElectricSplitField() = default;
169
170 /**
171 * Constructor of the field with a defined size in the x, y, z Cartesian
172 * dimensions
173 */
174 ElectricSplitField(int I_total, int J_total, int K_total)
175 : SplitField(I_total, J_total, K_total){};
176
177 /**
178 * @brief Interpolates a split E-field component to the centre of a Yee cell
179 *
180 * @param d Field component to interpolate
181 * @param cell Index (i,j,k) of the Yee cell to interpolate to the centre of
182 * @return double The interpolated component value
183 */
184 double interpolate_to_centre_of(AxialDirection d,
185 CellCoordinate cell) override;
186};
187
189protected:
190 int delta_n() override {
191 return 0;
192 };// TODO: no idea what this is or why it's needed
193
194public:
195 MagneticSplitField() = default;
196
197 /**
198 * Constructor of the field with a defined size in the x, y, z Cartesian
199 * dimensions
200 */
201 MagneticSplitField(int I_total, int J_total, int K_total)
202 : SplitField(I_total, J_total, K_total){};
203
204 /**
205 * @brief Interpolates a split E-field component to the centre of a Yee cell
206 *
207 * @param d Field component to interpolate
208 * @param cell Index (i,j,k) of the Yee cell to interpolate to the centre of
209 * @return double The interpolated component value
210 */
211 double interpolate_to_centre_of(AxialDirection d,
212 CellCoordinate cell) override;
213};
214
216protected:
217 int delta_n() override { return 0; }
218
219public:
220 CurrentDensitySplitField() = default;
221
222 /**
223 * Constructor of the field with a defined size in the x, y, z Cartesian
224 * dimensions
225 */
226 CurrentDensitySplitField(int I_total, int J_total, int K_total)
227 : SplitField(I_total, J_total, K_total){};
228
229 double interpolate_to_centre_of(AxialDirection d,
230 CellCoordinate cell) override {
231 return 0.;
232 };
233};
234
235/**
236 * A complex field defined over a grid. Has real and imaginary components
237 * at each (x, y, z) grid point
238 */
239class Field : public Grid {
240public:
241 double ft = 0.;// TODO: an explanation of what this is
242
243 std::complex<double> angular_norm = 0.;
244
245 // TODO: this is likely better as a set of complex arrays - use
246 // XYZTensor3D<std::complex<double>> This also makes implimenting
247 // normalise_volume, and the interpolation schemes, much easier...
250
251 /**
252 * Upper (u) and lower (l) indices in the x,y,z directions. e.g.
253 * il is the first non-pml cell in the i direction and iu the last in the
254 * corresponding split field grid
255 */
256 int il = 0, iu = 0, jl = 0, ju = 0, kl = 0, ku = 0;
257
258 /**
259 * Default no arguments constructor
260 */
261 Field() = default;
262
263 /**
264 * Constructor of the field with a defined size in the x, y, z Cartesian
265 * dimensions
266 */
267 Field(int I_total, int J_total, int K_total);
268
269 /**
270 * Allocate the memory appropriate for all the 3D tensors associated with
271 * this split field
272 */
273 void allocate();
274
275 /**
276 * Set all the values of all components of the field to zero
277 */
278 void zero();
279
280 /**
281 * Allocate and set to zero all components of the field
282 */
284 allocate();
285 zero();
286 }
287
288 /**
289 * @brief Normalises the field entries by dividing by the angular norm.
290 *
291 * Specifically,
292 * real[c][k][j][i] + i imag[c][k][j][i] = ( real[c][k][j][i] + i
293 * imag[c][k][j][i] ) / angular_norm
294 *
295 */
297
298 /**
299 * Set the phasors for this field, given a split field. Result gives field
300 * according to the exp(-iwt) convention
301 * @param F The split-field to read values from
302 * @param n The current timestep
303 * @param omega Angular frequency
304 * @param dt Timestep
305 * @param Nt Number of timesteps in a sinusoidal period
306 */
307 void set_phasors(SplitField &F, int n, double omega, double dt, int Nt);
308
309 // TODO: Docstring
310 /**
311 * @brief Compute the phasor_norm of the current field and add it to the
312 * current norm-value.
313 *
314 * Note that the calls:
315 * add_to_angular_norm(n, Nt, params), and
316 * add_to_angular_norm(n % Nt, Nt, params),
317 *
318 * are equivalent up to numerical precision when using n = tind, and Nt =
319 * Nsteps as set in the main simulation.
320 *
321 * @param n The number of timesteps INTO the current sinusoidal period
322 * @param Nt The number of timesteps in a sinusoidal period
323 * @param params The simulation parameters
324 */
325 void add_to_angular_norm(int n, int Nt, SimulationParameters &params);
326
327 // TODO: Docstring
328 std::complex<double> phasor_norm(double f, int n, double omega, double dt,
329 int Nt);
330
331 virtual double phase(int n, double omega, double dt) = 0;
332 /**
333 * @brief Interpolates a Field component to the centre of a Yee cell
334 *
335 * @param d Field component to interpolate
336 * @param cell Index (i,j,k) of the Yee cell to interpolate to the centre of
337 * @return std::complex<double> The interpolated field value
338 */
339 virtual std::complex<double>
340 interpolate_to_centre_of(AxialDirection d, CellCoordinate cell) = 0;
341
342 /**
343 * @brief Interpolates the Field over the range provided.
344 *
345 * Default range is to interpolate to the midpoint of all consecutive points.
346 *
347 * @param[out] x_out,y_out,z_out Output arrays for interpolated values
348 * @param i_lower,j_lower,k_lower Lower index for interpolation in the i,j,k
349 * directions, respectively
350 * @param i_upper,j_upper,k_upper Upper index for interpolation in the i,j,k
351 * directions, respectively
352 * @param mode Determines which field components to compute, based on the
353 * simulation Dimension
354 */
355 void interpolate_over_range(mxArray *x_out, mxArray *y_out, mxArray *z_out,
356 int i_lower, int i_upper, int j_lower,
357 int j_upper, int k_lower, int k_upper,
358 Dimension mode = Dimension::THREE);
359 /*! @copydoc interpolate_over_range */
360 void interpolate_over_range(mxArray *x_out, mxArray *y_out, mxArray *z_out,
361 Dimension mode = Dimension::THREE);
362
363 /**
364 * @brief Interpolates the Field's transverse electric components to the
365 * centre of Yee cell i,j,k
366 *
367 * @param[in] cell Yee cell index
368 * @param[out] x_at_centre,y_at_centre,z_at_centre Addresses to write
369 * interpolated values for the x,y,z components (respectively)
370 */
372 CellCoordinate cell, std::complex<double> *x_at_centre,
373 std::complex<double> *y_at_centre,
374 std::complex<double> *z_at_centre) = 0;
375 /**
376 * @brief Interpolates the Field's transverse magnetic components to the
377 * centre of Yee cell i,j,k
378 *
379 * @param[in] cell Yee cell index
380 * @param[out] x_at_centre,y_at_centre,z_at_centre Addresses to write
381 * interpolated values for the x,y,z components (respectively)
382 */
384 CellCoordinate cell, std::complex<double> *x_at_centre,
385 std::complex<double> *y_at_centre,
386 std::complex<double> *z_at_centre) = 0;
387
388 /**
389 * Set the values of all components in this field from another, equally sized
390 * field
391 */
392 void set_values_from(Field &other);
393
394 /**
395 * @brief Computes the maximum pointwise absolute difference of the other
396 * field to this one, divided by the largest absolute value of this field's
397 * components.
398 *
399 * Specifically, we compute and return the quantity
400 * \f$ \frac{ \max_{i,j,k}(this[k][j][i] - other[k][j][i]) }{
401 * \max_{i,j,k}this[k][j][i] } \f$ This quantity is used to determine
402 * convergence of phasors.
403 *
404 * The other field must have the same dimensions as this field.
405 *
406 * @param other The other field
407 * @return double Maximum relative pointwise absolute difference
408 */
410
411 ~Field();
412};
413
414class ElectricField : public Field {
415
416private:
417 double phase(int n, double omega, double dt) override;
418
419public:
420 ElectricField() = default;
421 ElectricField(int I_total, int J_total, int K_total)
422 : Field(I_total, J_total, K_total){};
423
424 /**
425 * @brief Interpolates an E-field component to the centre of a Yee cell
426 *
427 * @param d Field component to interpolate
428 * @param i,j,k Index (i,j,k) of the Yee cell to interpolate to the centre of
429 * @return std::complex<double> The interpolated component value
430 */
431 std::complex<double> interpolate_to_centre_of(AxialDirection d,
432 CellCoordinate cell) override;
433
434 /**
435 * @brief Interpolates the transverse electric components to the centre of Yee
436 * cell i,j,k.
437 *
438 * Ex and Ey are interpolated. Ez is set to a placeholder (default) value.
439 *
440 * @param[in] cell Yee cell index
441 * @param[out] x_at_centre,y_at_centre,z_at_centre Addresses to write
442 * interpolated values for the x,y,z components (respectively)
443 */
445 CellCoordinate cell, std::complex<double> *x_at_centre,
446 std::complex<double> *y_at_centre,
447 std::complex<double> *z_at_centre) override;
448 /**
449 * @brief Interpolates the transverse magnetic components to the centre of Yee
450 * cell i,j,k.
451 *
452 * Ez is interpolated. Ex and Ey are set to a placeholder (default) values.
453 *
454 * @param[in] cell Yee cell index
455 * @param[out] x_at_centre,y_at_centre,z_at_centre Addresses to write
456 * interpolated values for the x,y,z components (respectively)
457 */
459 CellCoordinate cell, std::complex<double> *x_at_centre,
460 std::complex<double> *y_at_centre,
461 std::complex<double> *z_at_centre) override;
462};
463
464class MagneticField : public Field {
465
466private:
467 double phase(int n, double omega, double dt) override;
468
469public:
470 MagneticField() = default;
471 MagneticField(int I_total, int J_total, int K_total)
472 : Field(I_total, J_total, K_total){};
473
474 /**
475 * @brief Interpolates an H-field component to the centre of a Yee cell
476 *
477 * @param d Field component to interpolate
478 * @param cell Index (i,j,k) of the Yee cell to interpolate to the centre of
479 * @return std::complex<double> The interpolated component value
480 */
481 std::complex<double> interpolate_to_centre_of(AxialDirection d,
482 CellCoordinate cell) override;
483
484 /**
485 * @brief Interpolates the transverse electric components to the centre of Yee
486 * cell i,j,k.
487 *
488 * Hz is interpolated. Hx and Hy are set to a placeholder (default) values.
489 *
490 * @param[in] cell Yee cell index
491 * @param[out] x_at_centre,y_at_centre,z_at_centre Addresses to write
492 * interpolated values for the x,y,z components (respectively)
493 */
495 CellCoordinate cell, std::complex<double> *x_at_centre,
496 std::complex<double> *y_at_centre,
497 std::complex<double> *z_at_centre) override;
498 /**
499 * @brief Interpolates the transverse magnetic components to the centre of Yee
500 * cell i,j,k.
501 *
502 * Hx and Hy are interpolated. Hz is set to a placeholder (default) value.
503 *
504 * @param[in] cell Yee cell index
505 * @param[out] x_at_centre,y_at_centre,z_at_centre Addresses to write
506 * interpolated values for the x,y,z components (respectively)
507 */
509 CellCoordinate cell, std::complex<double> *x_at_centre,
510 std::complex<double> *y_at_centre,
511 std::complex<double> *z_at_centre) override;
512};
513
514/**
515 * Structure to hold a field and allow saving it to a file
516 */
518private:
519 int nI = 0;//< Array size in the i direction
520 int nK = 0;//< Array size in the k direction
521public:
522 mxArray *matlab_array = nullptr;
523 double **array = nullptr;
524 std::string folder_name = "";
525
526 /**
527 * Allocate the arrays to hold the field
528 */
529 void allocate(int _nI, int _nK);
530
531 /**
532 * Export/save a field
533 *
534 * @param F Field to save
535 * @param stride Interval to compute the field component at
536 * @param iteration Iteration number of the main loop. Used in the filename
537 */
538 void export_field(SplitField &F, int stride, int iteration) const;
539
541};
Classes describing arrays, vertices etc.
Container for {ijk} or {IJK} grouped variables.
Definition field.h:215
double interpolate_to_centre_of(AxialDirection d, CellCoordinate cell) override
Interpolates a SplitField component to the centre of a Yee cell.
Definition field.h:229
CurrentDensitySplitField(int I_total, int J_total, int K_total)
Definition field.h:226
Definition dimensions.h:10
Definition field.h:414
void interpolate_transverse_magnetic_components(CellCoordinate cell, std::complex< double > *x_at_centre, std::complex< double > *y_at_centre, std::complex< double > *z_at_centre) override
Interpolates the transverse magnetic components to the centre of Yee cell i,j,k.
void interpolate_transverse_electric_components(CellCoordinate cell, std::complex< double > *x_at_centre, std::complex< double > *y_at_centre, std::complex< double > *z_at_centre) override
Interpolates the transverse electric components to the centre of Yee cell i,j,k.
std::complex< double > interpolate_to_centre_of(AxialDirection d, CellCoordinate cell) override
Interpolates an E-field component to the centre of a Yee cell.
Definition field.h:161
double interpolate_to_centre_of(AxialDirection d, CellCoordinate cell) override
Interpolates a split E-field component to the centre of a Yee cell.
ElectricSplitField(int I_total, int J_total, int K_total)
Definition field.h:174
Definition field.h:239
void allocate_and_zero()
Definition field.h:283
void add_to_angular_norm(int n, int Nt, SimulationParameters &params)
Compute the phasor_norm of the current field and add it to the current norm-value.
Field()=default
void zero()
int il
Definition field.h:256
void normalise_volume()
Normalises the field entries by dividing by the angular norm.
virtual void interpolate_transverse_magnetic_components(CellCoordinate cell, std::complex< double > *x_at_centre, std::complex< double > *y_at_centre, std::complex< double > *z_at_centre)=0
Interpolates the Field's transverse magnetic components to the centre of Yee cell i,...
void set_phasors(SplitField &F, int n, double omega, double dt, int Nt)
void set_values_from(Field &other)
void interpolate_over_range(mxArray *x_out, mxArray *y_out, mxArray *z_out, Dimension mode=Dimension::THREE)
Interpolates the Field over the range provided.
double normalised_difference(Field &other)
Computes the maximum pointwise absolute difference of the other field to this one,...
virtual std::complex< double > interpolate_to_centre_of(AxialDirection d, CellCoordinate cell)=0
Interpolates a Field component to the centre of a Yee cell.
virtual void interpolate_transverse_electric_components(CellCoordinate cell, std::complex< double > *x_at_centre, std::complex< double > *y_at_centre, std::complex< double > *z_at_centre)=0
Interpolates the Field's transverse electric components to the centre of Yee cell i,...
void interpolate_over_range(mxArray *x_out, mxArray *y_out, mxArray *z_out, int i_lower, int i_upper, int j_lower, int j_upper, int k_lower, int k_upper, Dimension mode=Dimension::THREE)
Interpolates the Field over the range provided.
Field(int I_total, int J_total, int K_total)
void allocate()
Definition field.h:34
int max_IJK_tot() const
Definition field.h:49
void set_preferred_interpolation_methods(tdms_flags::InterpolationMethod im)
Set the preferred interpolation methods.
Definition field.h:54
Definition field.h:464
void interpolate_transverse_electric_components(CellCoordinate cell, std::complex< double > *x_at_centre, std::complex< double > *y_at_centre, std::complex< double > *z_at_centre) override
Interpolates the transverse electric components to the centre of Yee cell i,j,k.
std::complex< double > interpolate_to_centre_of(AxialDirection d, CellCoordinate cell) override
Interpolates an H-field component to the centre of a Yee cell.
void interpolate_transverse_magnetic_components(CellCoordinate cell, std::complex< double > *x_at_centre, std::complex< double > *y_at_centre, std::complex< double > *z_at_centre) override
Interpolates the transverse magnetic components to the centre of Yee cell i,j,k.
Definition field.h:188
MagneticSplitField(int I_total, int J_total, int K_total)
Definition field.h:201
double interpolate_to_centre_of(AxialDirection d, CellCoordinate cell) override
Interpolates a split E-field component to the centre of a Yee cell.
Class storing the various constants and behaviour flags for one executation of the tdms executable.
Definition simulation_parameters.h:69
Definition field.h:59
void initialise_fftw_plan(int n_threads, int size, EHVec &eh_vec)
A split field defined over a grid.
Definition field.h:84
virtual double interpolate_to_centre_of(AxialDirection d, CellCoordinate cell)=0
Interpolates a SplitField component to the centre of a Yee cell.
void allocate_and_zero()
Definition field.h:127
SplitFieldComponent zy
Definition field.h:100
SplitField()=default
double largest_field_value()
Fetches the largest absolute value of the field.
void zero()
void initialise_fftw_plan(int n_threads, EHVec &eh_vec)
SplitFieldComponent yz
Definition field.h:96
void allocate()
SplitFieldComponent xz
Definition field.h:92
SplitField(int I_total, int J_total, int K_total)
SplitFieldComponent yx
Definition field.h:94
SplitFieldComponent zx
Definition field.h:98
SplitFieldComponent xy
Definition field.h:90
Definition field.h:517
void export_field(SplitField &F, int stride, int iteration) const
void allocate(int _nI, int _nK)
Definition arrays.h:19
Defines a class that serves as an explicit converter between MATLAB pointers and array dimensions.
Organises enumerated constants, names, and classes for handling flag-variables that are passed to TDM...
Includes MATLAB headers for I/O.
InterpolationMethod
Definition input_flags.h:37
Classes collecting parameters for the simulation.
Dimension
Determines whether the simulation will compute all field components, or only the TE or TM modal compo...
Definition simulation_parameters.h:39
A structure for holding three values, which typically pertain to the same quantity but for each of th...
Definition cell_coordinate.h:21
int max() const
Return the maximum of i,j,k.
Definition cell_coordinate.h:27