Skip to content

Commit d652b49

Browse files
committed
Add tests for differential operator
1 parent 98bba9b commit d652b49

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

tests/test_diffop.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// SPDX-FileCopyrightText: 2025 VTT Technical Research Centre of Finland Ltd
2+
// SPDX-License-Identifier: AGPL-3.0-or-later
3+
4+
#include <pfc/diffop.hpp>
5+
#include <pfc/fft.hpp>
6+
#include <pfc/field.hpp>
7+
#include <pfc/world.hpp>
8+
9+
#include <catch2/catch_test_macros.hpp>
10+
#include <catch2/matchers/catch_matchers_floating_point.hpp>
11+
12+
using namespace pfc;
13+
14+
TEST_CASE("Differentiate in all directions", "[SpectralDifferentiator]") {
15+
// Setup
16+
auto lo{-M_PI, -M_PI, -M_PI};
17+
auto hi{M_PI, M_PI, M_PI};
18+
auto size{128, 128, 128};
19+
auto world = world::create(lo, hi, size);
20+
auto fft = fft::create(world);
21+
auto diff = diffop::create(world, fft); // Creates spectral differentiator
22+
23+
// Input function
24+
auto f = [](auto r) {
25+
return exp(sin(r[0])) * exp(sin(2 * r[1])) * exp(sin(3 * r[2]));
26+
};
27+
auto df_dx = [](auto r) {
28+
return exp(sin(r[0]) + sin(2 * r[1]) + sin(3 * r[2])) * cos(r[0]);
29+
};
30+
31+
auto u = field::create(world, f);
32+
auto eps = 1e-9; // Tolerance
33+
34+
// Apply spectral differentiation in x direction
35+
SECTION("Differentiation in x direction") {
36+
fft(diff, u); // forward FFT: F
37+
auto dx_op = get_operator(diff, diffop::dx); // ∂/∂x operator
38+
auto F = get_fft(diff); // F = forward FFT of u
39+
auto F_buf = get_fft_buffer(diff); // F_buf = buffer for FFT results
40+
apply_operator(F_buf, F, dx_op); // F_buf = ∂/∂x F
41+
auto du = similar(u); // du = ∂/∂x u
42+
ifft(diff, du, F_buf); // inverse FFT: du = ∂/∂x u
43+
auto true_du = field::create(world, df_dx);
44+
REQUIRE(isapprox(du, true_du, eps));
45+
}
46+
47+
// Apply spectral differentiation in y direction using high-level interface
48+
SECTION("Differentiation in y direction") {
49+
fft(diff, u); // forward FFT: F
50+
auto dy_op = get_operator(diff, diffop::dy); // ∂/∂y operator
51+
auto du = differentiate(diff, dy_op); // assumes F is already computed
52+
auto true_du = field::create(world, df_dy);
53+
REQUIRE(isapprox(du, true_du, eps));
54+
}
55+
56+
SECTION("Differentiation in z direction") {
57+
auto du = differentiate(diff, u, diffop::dz); // calculates fft internally
58+
auto true_du = field::create(world, df_dz);
59+
REQUIRE(isapprox(du, true_du, eps));
60+
}
61+
62+
SECTION("Second derivatives") {
63+
auto diffresult = differentiate(diff, u); // calculates fft internally + all ops
64+
REQUIRE(isapprox(dx2(diffresult), field::create(world, d2f_dx2)));
65+
REQUIRE(isapprox(dy2(diffresult), field::create(world, d2f_dy2)));
66+
REQUIRE(isapprox(dz2(diffresult), field::create(world, d2f_dz2)));
67+
REQUIRE(isapprox(laplace(diffresult), field::create(world, lap_f)));
68+
}
69+
70+
SECTION("Differentiation in xy direction") {
71+
fft(diff, u); // forward FFT: F
72+
auto dx_op = get_operator(diff, diffop::dx); // ∂/∂x operator
73+
auto dy_op = get_operator(diff, diffop::dy); // ∂/∂y operator
74+
auto du = differentiate(diff, dx_op, dy_op); // assumes F is already computed
75+
auto true_du = field::create(world, d2f_dxdy);
76+
REQUIRE(isapprox(du, true_du));
77+
}
78+
}

0 commit comments

Comments
 (0)