Skip to content

Commit e820ff2

Browse files
authored
Merge pull request #2 from samwyss/simpler-refactor
Simple architecture refactor
2 parents 7138fb2 + 13089a5 commit e820ff2

File tree

5 files changed

+176
-129
lines changed

5 files changed

+176
-129
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ add_library(Core
131131
src/core/world.h
132132
src/core/config.cpp
133133
src/core/config.h
134-
src/core/emengine.cpp
135-
src/core/emengine.h
134+
src/core/fdtd_engine.cpp
135+
src/core/fdtd_engine.h
136136
)
137137

138138
target_include_directories(Core
Lines changed: 95 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "emengine.h"
1+
#include "fdtd_engine.h"
22

33
template <std::floating_point T>
44
FDTDGeometry<T>::FDTDGeometry(const Config<T> &config)
@@ -7,45 +7,44 @@ FDTDGeometry<T>::FDTDGeometry(const Config<T> &config)
77
mu(mu_r * VAC_PERMEABILITY<T>), sigma(config.sigma) {
88

99
SPDLOG_TRACE("enter FDTDGeometry<T>::FDTDGeometry");
10-
SPDLOG_DEBUG("FDTD bounding box (m): {:.3e} x {:.3e} x {:.3e}", len.x, len.y,
10+
SPDLOG_DEBUG("bounding box (m): {:.3e} x {:.3e} x {:.3e}", len.x, len.y,
1111
len.z);
1212

1313
// (m) maximum spatial step based on maximum frequency
1414
const T ds_min_wavelength =
1515
VAC_SPEED_OF_LIGHT<T> /
1616
(sqrt(ep_r * mu_r) * static_cast<T>(config.num_vox_min_wavelength) *
1717
config.max_frequency);
18-
SPDLOG_DEBUG(
19-
"FDTD maximum spatial step based on maximum frequency (m): {:.3e}",
20-
ds_min_wavelength);
18+
SPDLOG_DEBUG("maximum spatial step based on maximum frequency (m): {:.3e}",
19+
ds_min_wavelength);
2120

2221
// (m) maximum spatial step based on minimum feature size
2322
const T ds_min_feature_size = std::min({len.x, len.y, len.z}) /
2423
static_cast<T>(config.num_vox_min_feature);
25-
SPDLOG_DEBUG("FDTD maximum spatial step based on feature size (m): {:.3e}",
24+
SPDLOG_DEBUG("maximum spatial step based on feature size (m): {:.3e}",
2625
ds_min_feature_size);
2726

2827
// (m) maximum required spatial step
2928
const T ds = std::min({ds_min_wavelength, ds_min_feature_size});
30-
SPDLOG_DEBUG("FDTD maximum spatial step (m): {:.3e}", ds);
29+
SPDLOG_DEBUG("maximum spatial step (m): {:.3e}", ds);
3130

3231
// number of voxels in each direction snapped to ds
3332
nv = {static_cast<size_t>(ceil(static_cast<double>(len.x) / ds)),
3433
static_cast<size_t>(ceil(static_cast<double>(len.y) / ds)),
3534
static_cast<size_t>(ceil(static_cast<double>(len.z) / ds))};
36-
SPDLOG_DEBUG("FDTD voxels per field: {} x {} x {}", nv.x, nv.y, nv.z);
37-
SPDLOG_DEBUG("FDTD voxels to update each step: {}", 6 * nv.x);
35+
SPDLOG_DEBUG("field voxel dimensions: {} x {} x {}", nv.x, nv.y, nv.z);
36+
SPDLOG_DEBUG("voxels to update each step: {}", 6 * nv.x);
3837

3938
// (m) final spatial steps
4039
d = {len.x / static_cast<T>(nv.x), len.y / static_cast<T>(nv.y),
4140
len.z / static_cast<T>(nv.z)};
42-
SPDLOG_DEBUG("FDTD voxel size (m): {:.3e} x {:.3e} x {:.3e}", d.x, d.y, d.z);
41+
SPDLOG_DEBUG("voxel size (m): {:.3e} x {:.3e} x {:.3e}", d.x, d.y, d.z);
4342

4443
// (m^-1) inverse spatial steps
4544
d_inv = {static_cast<T>(1.0) / d.x, static_cast<T>(1.0) / d.y,
4645
static_cast<T>(1.0) / d.z};
47-
SPDLOG_DEBUG("FDTD inverse voxel size (m) , {:.3e} x {:.3e} x {:.3e}",
48-
d_inv.x, d_inv.y, d_inv.z);
46+
SPDLOG_DEBUG("inverse voxel size (m) , {:.3e} x {:.3e} x {:.3e}", d_inv.x,
47+
d_inv.y, d_inv.z);
4948

5049
SPDLOG_TRACE("exit FDTDGeometry<T>::FDTDGeometry");
5150
}
@@ -77,7 +76,7 @@ std::expected<FDTDEngine<T>, std::string>
7776
FDTDEngine<T>::create(const Config<T> &config) {
7877
SPDLOG_TRACE("enter FDTDEngine<T>::create");
7978
try {
80-
// todo why not const like FDTD geometry?
79+
// todo why not const like FDTDGeometry?
8180
FDTDEngine engine(config);
8281
SPDLOG_TRACE("exit FDTDEngine<T>::create with success");
8382
return engine;
@@ -88,83 +87,16 @@ FDTDEngine<T>::create(const Config<T> &config) {
8887
}
8988

9089
template <std::floating_point T>
91-
std::expected<void, std::string> FDTDEngine<T>::advance_to(const T end_t) {
92-
SPDLOG_TRACE("enter FDTDEngine<T>::advance_to");
93-
SPDLOG_DEBUG("FDTD current time is {:.3e} (s)", time);
94-
SPDLOG_DEBUG("FDTD advance time to {:.3e} (s)", end_t);
95-
if (end_t > time) {
96-
// (s) time difference between current state and end time
97-
const T adv_t = end_t - time;
98-
99-
if (const auto adv_by_result = advance_by(adv_t);
100-
!adv_by_result.has_value()) {
101-
SPDLOG_CRITICAL("FDTD advance time by advance_by returned with error: {}",
102-
adv_by_result.error());
103-
return std::unexpected(adv_by_result.error());
104-
}
105-
106-
} else {
107-
SPDLOG_WARN(
108-
"end time of {:.3e} (s) is not greater than current time of {:.3e} (s)",
109-
end_t, time);
110-
}
111-
112-
SPDLOG_TRACE("exit FDTDEngine<T>::advance_to");
113-
return {};
114-
}
115-
116-
template <std::floating_point T>
117-
std::expected<void, std::string> FDTDEngine<T>::advance_by(const T adv_t) {
118-
SPDLOG_TRACE("enter FDTDEngine<T>::advance_by");
119-
SPDLOG_DEBUG("FDTD advance time by {:.3e} (s)", adv_t);
120-
121-
// (s) initial time
122-
// NOTE only used if SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE
123-
[[maybe_unused]] const auto init_time = time;
124-
125-
// number of steps required by CFL condition
126-
const size_t steps = calc_cfl_steps(adv_t);
127-
128-
// (s) time step
129-
const T dt = adv_t / static_cast<T>(steps);
130-
SPDLOG_DEBUG("FDTD timestep: {:.3e} (s)", dt);
131-
132-
// preprocess loop constants
133-
const T ea = 1.0 / (geom.ep / dt + geom.sigma / 2.0);
134-
const T eb = geom.ep / dt - geom.sigma / 2.0;
135-
const T hxa = dt * geom.d_inv.x / geom.mu;
136-
const T hya = dt * geom.d_inv.y / geom.mu;
137-
const T hza = dt * geom.d_inv.z / geom.mu;
138-
139-
// loop start time
140-
[[maybe_unused]] const spdlog::stopwatch watch;
141-
142-
// main time loop
143-
SPDLOG_DEBUG("FDTD enter main time loop");
144-
try {
145-
for (uint64_t i = 0; i < steps; ++i) {
90+
uint64_t FDTDEngine<T>::calc_num_steps(const T adv_t) const {
91+
SPDLOG_TRACE("enter FDTDEngine<T>::calc_num_steps");
14692

147-
// advance by one step
148-
step(dt, ea, eb, hxa, hya, hza);
93+
// find maximum number of timesteps required for any solver
94+
const uint64_t max_num_steps = calc_cfl_steps(adv_t);
95+
SPDLOG_DEBUG("maximum number of steps required by any solver: {}",
96+
max_num_steps);
14997

150-
SPDLOG_TRACE("step: {}/{} elapsed time: {:.5e}/{:.5e} (s)", i + 1, steps,
151-
time, init_time + adv_t);
152-
}
153-
} catch (const std::runtime_error &err) {
154-
SPDLOG_CRITICAL("FDTD main time loop returned with error: {}", err.what());
155-
return std::unexpected(err.what());
156-
}
157-
SPDLOG_DEBUG("FDTD exit main time loop with success");
158-
159-
// basic loop performance diagnostics
160-
[[maybe_unused]] const auto loop_time = watch.elapsed().count();
161-
[[maybe_unused]] const auto num_cells = 6 * e.x.size() * steps;
162-
SPDLOG_INFO("loop runtime: {:.3e} (s)", loop_time);
163-
SPDLOG_INFO("voxel compute rate {:.3e}",
164-
static_cast<double>(num_cells) / loop_time);
165-
166-
SPDLOG_TRACE("exit FDTDEngine<T>::advance_by");
167-
return {};
98+
SPDLOG_TRACE("exit FDTDEngine<T>::calc_num_steps");
99+
return max_num_steps;
168100
}
169101

170102
template <std::floating_point T>
@@ -175,49 +107,95 @@ uint64_t FDTDEngine<T>::calc_cfl_steps(const T time_span) const {
175107
1.0 / (VAC_SPEED_OF_LIGHT<T> / sqrt(geom.ep_r * geom.mu_r) *
176108
sqrt(pow(geom.d_inv.x, 2) + pow(geom.d_inv.y, 2) +
177109
pow(geom.d_inv.z, 2)));
178-
SPDLOG_DEBUG(
179-
"FDTD maximum possible timesteps to satisfy CFL condition: {:.3e} (s)",
180-
maximum_dt);
110+
SPDLOG_DEBUG("maximum possible timestep to satisfy CFL condition (s): {:.3e}",
111+
maximum_dt);
181112

182113
const T num_steps = static_cast<uint64_t>(ceil(time_span / maximum_dt));
183-
SPDLOG_DEBUG("FDTD steps required to satisfy CFL condition: {}", num_steps);
114+
SPDLOG_DEBUG("steps required to satisfy CFL condition: {}", num_steps);
184115

185116
SPDLOG_TRACE("exit FDTDEngine<T>::calc_cfl_steps");
186117
return num_steps;
187118
}
188119

189-
template <std::floating_point T>
190-
void FDTDEngine<T>::step(const T dt, const T ea, const T eb, const T hxa,
191-
const T hya, const T hza) {
120+
template <std::floating_point T> void FDTDEngine<T>::step(const T dt) {
121+
SPDLOG_TRACE("enter FDTDEngine<T>::step");
122+
123+
// TODO it would be nice to not need to recalculate these every time step is
124+
// TODO called, the performance penalty of this has yet to be assed however
125+
126+
// electric field a loop constant
127+
const T ea = 1.0 / (geom.ep / dt + geom.sigma / 2.0);
128+
SPDLOG_TRACE("ea loop constant: {:.3e}", ea);
129+
130+
// electric field b loop constant
131+
const T eb = geom.ep / dt - geom.sigma / 2.0;
132+
SPDLOG_TRACE("eb loop constant: {:.3e}", eb);
133+
134+
// magnetic field a loop constant for x-component
135+
const T hxa = dt * geom.d_inv.x / geom.mu;
136+
SPDLOG_TRACE("hxa loop constant: {:.3e}", hxa);
137+
138+
// magnetic field a loop constant for y-component
139+
const T hya = dt * geom.d_inv.y / geom.mu;
140+
SPDLOG_TRACE("hya loop constant: {:.3e}", hya);
141+
142+
// magnetic field a loop constant for z-component
143+
const T hza = dt * geom.d_inv.z / geom.mu;
144+
SPDLOG_TRACE("hza loop constant: {:.3e}", hza);
145+
192146
// half timestep update before updating magnetic fields
193147
time += ONE_OVER_TWO<T> * dt;
148+
SPDLOG_TRACE("advance half time step to (s): {:.5e}", time);
194149

195150
// update magnetic fields
196151
update_h(hxa, hya, hza);
197152

198153
// half timestep update before updating electric fields
199154
time += ONE_OVER_TWO<T> * dt;
155+
SPDLOG_TRACE("advance half time step to (s): {:.5e}", time);
200156

201157
// update electric fields
202158
update_e(ea, eb);
159+
160+
SPDLOG_TRACE("exit FDTDEngine<T>::step");
161+
}
162+
163+
template <std::floating_point T>
164+
uint64_t FDTDEngine<T>::get_field_num_vox() const {
165+
SPDLOG_TRACE("enter FDTDEngine<T>::get_field_num_vox");
166+
167+
const auto num_vox = e.x.size();
168+
169+
SPDLOG_TRACE("exit FDTDEngine<T>::get_field_num_vox");
170+
return num_vox;
203171
}
204172

205173
template <std::floating_point T>
206174
void FDTDEngine<T>::update_e(const T ea, const T eb) {
175+
SPDLOG_TRACE("enter FDTDEngine<T>::update_e");
176+
207177
update_ex(ea, eb);
208178
update_ey(ea, eb);
209179
update_ez(ea, eb);
180+
181+
SPDLOG_TRACE("exit FDTDEngine<T>::update_e");
210182
}
211183

212184
template <std::floating_point T>
213185
void FDTDEngine<T>::update_h(const T hxa, const T hya, const T hza) {
186+
SPDLOG_TRACE("enter FDTDEngine<T>::update_h");
187+
214188
update_hx(hya, hza);
215189
update_hy(hxa, hza);
216190
update_hz(hya, hza);
191+
192+
SPDLOG_TRACE("exit FDTDEngine<T>::update_h");
217193
}
218194

219195
template <std::floating_point T>
220196
void FDTDEngine<T>::update_ex(const T ea, const T eb) {
197+
SPDLOG_TRACE("enter FDTDEngine<T>::update_ex");
198+
221199
// assumes PEC outer boundary
222200
for (size_t i = 1; i < e.x.extent(0) - 1; ++i) {
223201
for (size_t j = 1; j < e.x.extent(1) - 1; ++j) {
@@ -228,10 +206,14 @@ void FDTDEngine<T>::update_ex(const T ea, const T eb) {
228206
}
229207
}
230208
}
209+
210+
SPDLOG_TRACE("exit FDTDEngine<T>::update_ex");
231211
}
232212

233213
template <std::floating_point T>
234214
void FDTDEngine<T>::update_ey(const T ea, const T eb) {
215+
SPDLOG_TRACE("enter FDTDEngine<T>::update_ey");
216+
235217
// assumes PEC outer boundary
236218
for (size_t i = 1; i < e.y.extent(0) - 1; ++i) {
237219
for (size_t j = 1; j < e.y.extent(1) - 1; ++j) {
@@ -242,10 +224,14 @@ void FDTDEngine<T>::update_ey(const T ea, const T eb) {
242224
}
243225
}
244226
}
227+
228+
SPDLOG_TRACE("exit FDTDEngine<T>::update_ey");
245229
}
246230

247231
template <std::floating_point T>
248232
void FDTDEngine<T>::update_ez(const T ea, const T eb) {
233+
SPDLOG_TRACE("enter FDTDEngine<T>::update_ez");
234+
249235
// assumes PEC outer boundary
250236
for (size_t i = 1; i < e.z.extent(0) - 1; ++i) {
251237
for (size_t j = 1; j < e.z.extent(1) - 1; ++j) {
@@ -256,10 +242,14 @@ void FDTDEngine<T>::update_ez(const T ea, const T eb) {
256242
}
257243
}
258244
}
245+
246+
SPDLOG_TRACE("exit FDTDEngine<T>::update_ez");
259247
}
260248

261249
template <std::floating_point T>
262250
void FDTDEngine<T>::update_hx(const T hya, const T hza) {
251+
SPDLOG_TRACE("enter FDTDEngine<T>::update_hx");
252+
263253
// todo correctly implement for PEC boundary
264254
for (size_t i = 1; i < h.x.extent(0) - 1; ++i) {
265255
for (size_t j = 1; j < h.x.extent(1) - 1; ++j) {
@@ -269,10 +259,14 @@ void FDTDEngine<T>::update_hx(const T hya, const T hza) {
269259
}
270260
}
271261
}
262+
263+
SPDLOG_TRACE("exit FDTDEngine<T>::update_hx");
272264
}
273265

274266
template <std::floating_point T>
275267
void FDTDEngine<T>::update_hy(const T hxa, const T hza) {
268+
SPDLOG_TRACE("enter FDTDEngine<T>::update_hy");
269+
276270
// todo correctly implement for PEC boundary
277271
for (size_t i = 1; i < h.y.extent(0) - 1; ++i) {
278272
for (size_t j = 1; j < h.y.extent(1) - 1; ++j) {
@@ -282,10 +276,14 @@ void FDTDEngine<T>::update_hy(const T hxa, const T hza) {
282276
}
283277
}
284278
}
279+
280+
SPDLOG_TRACE("exit FDTDEngine<T>::update_hy");
285281
}
286282

287283
template <std::floating_point T>
288284
void FDTDEngine<T>::update_hz(const T hxa, const T hya) {
285+
SPDLOG_TRACE("enter FDTDEngine<T>::update_hz");
286+
289287
// todo correctly implement for PEC boundary
290288
for (size_t i = 1; i < h.z.extent(0) - 1; ++i) {
291289
for (size_t j = 1; j < h.z.extent(1) - 1; ++j) {
@@ -295,6 +293,8 @@ void FDTDEngine<T>::update_hz(const T hxa, const T hya) {
295293
}
296294
}
297295
}
296+
297+
SPDLOG_TRACE("exit FDTDEngine<T>::update_hz");
298298
}
299299

300300
// explicit template instantiation

0 commit comments

Comments
 (0)