Skip to content

Commit 74c8d8c

Browse files
committed
refactor: Simplify periodic BC implementation
Signed-off-by: Sietze van Buuren <s.van.buuren@gmail.com>
1 parent b077f32 commit 74c8d8c

File tree

1 file changed

+24
-29
lines changed

1 file changed

+24
-29
lines changed

include/slopes.hpp

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,11 @@ struct setNaturalSplineBoundaryCondition<BoundaryConditionType::Clamped, T, Tx,
230230

231231

232232
template <typename T>
233-
void cyclic_thomas_algorithm(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c, std::vector<T> &d)
233+
void cyclic_thomas_algorithm(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c, std::vector<T> &d, const std::size_t exclude_rows=0)
234234
{
235235
// See https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm#Variants
236236

237-
const auto nx = d.size();
237+
const auto nx = d.size() - exclude_rows; // last exclude_rows rows are not used
238238

239239
std::vector<T> cmod(nx);
240240
std::vector<T> v(nx);
@@ -243,27 +243,31 @@ void cyclic_thomas_algorithm(const std::vector<T> &a, const std::vector<T> &b, c
243243
v[1] = -a[1]/b[1];
244244
d[1] = d[1]/b[1];
245245

246-
for (auto ix = 2; ix < nx-1; ++ix) {
246+
for (auto ix = 2; ix < nx-1; ++ix)
247+
{
247248
const T m = T(1.0)/(b[ix] - a[ix]*cmod[ix-1]);
248249
cmod[ix] = m*c[ix];
249250
v[ix] = (T(0.0) - a[ix]*v[ix-1]) * m;
250251
d[ix] = (d[ix] - a[ix]*d[ix-1]) * m;
251252
}
252253

253254
const T m = T(1.0)/(b[nx-1] - a[nx-1]*cmod[nx-2]);
254-
cmod[nx - 1] = m*c[nx-1];
255-
v[nx - 1] = m*(-c[0] - a[nx-1]*v[nx-2]);
256-
d[nx - 1] = m*(d[nx-1] - a[nx-1]*d[nx-2]);
255+
cmod[nx-1] = m*c[nx-1];
256+
v[nx-1] = m*(-c[0] - a[nx-1]*v[nx-2]);
257+
d[nx-1] = m*(d[nx-1] - a[nx-1]*d[nx-2]);
257258

258-
for (auto ix = nx - 2; ix >= 1; --ix) {
259+
for (auto ix = nx - 2; ix >= 1; --ix)
260+
{
259261
v[ix] -= cmod[ix]*v[ix+1];
260262
d[ix] -= cmod[ix]*d[ix+1];
261263
}
262264

263265
d[0] = (d[0] - a[0]*d[nx-1] - c[0]*d[1])/(b[0] + a[0]*v[nx-1] + c[0]*v[1]);
264266

265267
for (auto ix = 1; ix < nx; ++ix)
268+
{
266269
d[ix] += d[0]*v[ix];
270+
}
267271
}
268272

269273

@@ -274,7 +278,8 @@ struct setNaturalSplineBoundaryCondition<BoundaryConditionType::Periodic, T, Tx,
274278

275279
// Periodic boundary conditions, it is assumed that f[0] == f[nx-1] !
276280

277-
const auto nsys = a.size();
281+
// last equation is for periodicity and not used in cyclic thomas algorithm
282+
const auto nsys = d.size() - 1;
278283

279284
// Row 0
280285
{
@@ -298,7 +303,9 @@ struct setNaturalSplineBoundaryCondition<BoundaryConditionType::Periodic, T, Tx,
298303
d[nsys-1] = 3.0*((f[nsys-1] - f[nsys-2])/(dxL*dxL) + (f[0] - f[nsys-1])/(dxR*dxR));
299304
}
300305

301-
cyclic_thomas_algorithm<T>(a, b, c, d);
306+
cyclic_thomas_algorithm<T>(a, b, c, d, 1); // exclude last row
307+
308+
d.back() = d.front(); // duplicate endpoint slope for periodic BC
302309
}
303310
};
304311

@@ -310,18 +317,17 @@ std::vector<T> natural_spline_slopes(const Tx x, const Tf f)
310317

311318
const auto nx = x.size();
312319

313-
// Periodic with duplicated endpoint → reduce system
314-
constexpr bool is_periodic = (BC == BoundaryConditionType::Periodic);
315-
const auto nsys = is_periodic ? nx - 1 : nx;
316-
317320
// vectors that fill up the tridiagonal matrix
318-
std::vector<T> a(nsys, T{0}); // first value of a is only used for periodic BC
319-
std::vector<T> b(nsys, T{0});
320-
std::vector<T> c(nsys, T{0}); // last value of c is only used for periodic BC
321+
std::vector<T> a(nx, T{0}); // first value of a is only used for periodic BC
322+
std::vector<T> b(nx, T{0});
323+
std::vector<T> c(nx, T{0}); // last value of c is only used for periodic BC
321324
// right hand side
322-
std::vector<T> d(nsys, T{0});
325+
std::vector<T> d(nx, T{0});
323326

324-
for (auto i = 1; i < nsys-1; ++i)
327+
// For Periodic BD the last row is not used
328+
constexpr bool is_periodic = (BC == BoundaryConditionType::Periodic);
329+
330+
for (auto i = 1; i < (is_periodic ? nx-2 : nx-1); ++i)
325331
{
326332
T dxL = x[i] - x[i-1];
327333
T dxR = x[i+1] - x[i];
@@ -333,17 +339,6 @@ std::vector<T> natural_spline_slopes(const Tx x, const Tf f)
333339

334340
setNaturalSplineBoundaryCondition<BC, T, Tx, Tf>{}(x, f, a, b, c, d);
335341

336-
if constexpr (is_periodic)
337-
{
338-
std::vector<T> full(nx);
339-
for (auto i = 0; i < nsys; ++i)
340-
{
341-
full[i] = d[i];
342-
}
343-
full[nx-1] = full[0]; // duplicate endpoint slope
344-
return full;
345-
}
346-
347342
return d;
348343
}
349344

0 commit comments

Comments
 (0)