10 #include <catch2/catch_test_macros.hpp>
11 #include <catch2/matchers/catch_matchers_floating_point.hpp>
15 using namespace nmodl;
20 SCENARIO(
"Non-linear system to solve with Newton Solver",
"[analytic][solver]") {
21 GIVEN(
"1 linear eq") {
23 void operator()(
const Eigen::Matrix<double, 1, 1>& X,
24 Eigen::Matrix<double, 1, 1>& ,
25 Eigen::Matrix<double, 1, 1>& F,
26 Eigen::Matrix<double, 1, 1>& J)
const {
28 F[0] = -3.0 * X[0] + 3.0;
33 Eigen::Matrix<double, 1, 1> X{22.2536};
34 Eigen::Matrix<double, 1, 1> dX;
35 Eigen::Matrix<double, 1, 1> F;
36 Eigen::Matrix<double, 1, 1> J;
40 THEN(
"find the solution") {
43 REQUIRE(iter_newton == 1);
44 REQUIRE_THAT(X[0], Catch::Matchers::WithinRel(1.0, 0.01));
49 GIVEN(
"1 non-linear eq") {
51 void operator()(
const Eigen::Matrix<double, 1, 1>& X,
52 Eigen::Matrix<double, 1, 1>& ,
53 Eigen::Matrix<double, 1, 1>& F,
54 Eigen::Matrix<double, 1, 1>& J)
const {
55 F[0] = -3.0 * X[0] + std::sin(X[0]) + std::log(X[0] * X[0] + 11.435243) + 3.0;
56 J(0, 0) = -3.0 + std::cos(X[0]) + 2.0 * X[0] / (X[0] * X[0] + 11.435243);
59 Eigen::Matrix<double, 1, 1> X{-0.21421};
60 Eigen::Matrix<double, 1, 1> dX;
61 Eigen::Matrix<double, 1, 1> F;
62 Eigen::Matrix<double, 1, 1> J;
66 THEN(
"find the solution") {
69 REQUIRE(iter_newton > 0);
70 REQUIRE_THAT(X[0], Catch::Matchers::WithinRel(2.19943987001206, 0.01));
75 GIVEN(
"system of 2 non-linear eqs") {
77 void operator()(
const Eigen::Matrix<double, 2, 1>& X,
78 Eigen::Matrix<double, 2, 1>& ,
79 Eigen::Matrix<double, 2, 1>& F,
80 Eigen::Matrix<double, 2, 2>& J)
const {
81 F[0] = -3.0 * X[0] * X[1] + X[0] + 2.0 * X[1] - 1.0;
82 F[1] = 4.0 * X[0] - 0.29999999999999999 * std::pow(X[1], 2) + X[1] + 0.4;
83 J(0, 0) = -3.0 * X[1] + 1.0;
84 J(0, 1) = -3.0 * X[0] + 2.0;
86 J(1, 1) = -0.59999999999999998 * X[1] + 1.0;
89 Eigen::Matrix<double, 2, 1> X{0.2, 0.4};
90 Eigen::Matrix<double, 2, 1> dX;
91 Eigen::Matrix<double, 2, 1> F;
92 Eigen::Matrix<double, 2, 2> J;
96 THEN(
"find a solution") {
99 REQUIRE(iter_newton > 0);
104 GIVEN(
"system of 3 non-linear eqs") {
107 double _y_old = -231.5;
108 double _z_old = 1.4565;
115 void operator()(
const Eigen::Matrix<double, 3, 1>& X,
116 Eigen::Matrix<double, 3, 1>& ,
117 Eigen::Matrix<double, 3, 1>& F,
118 Eigen::Matrix<double, 3, 3>& J)
const {
119 F(0) = -(-_x_old - dt * (a * std::pow(X[0], 2) + X[1]) + X[0]);
120 F(1) = -(_y_old - dt * (a * X[0] + b * X[1] + d) + X[1]);
121 F(2) = -(_z_old - dt * (e * z - 3.0 * X[0] + 2.0 * X[1]) + X[2]);
122 J(0, 0) = 2.0 * a * dt * X[0] - 1.0;
126 J(1, 1) = b * dt - 1.0;
130 J(2, 2) = dt * e - 1.0;
133 Eigen::Matrix<double, 3, 1> X{0.21231, 0.4435, -0.11537};
134 Eigen::Matrix<double, 3, 1> dX;
135 Eigen::Matrix<double, 3, 1> F;
136 Eigen::Matrix<double, 3, 3> J;
140 THEN(
"find a solution") {
141 CAPTURE(iter_newton);
143 REQUIRE(iter_newton > 0);
148 GIVEN(
"system of 4 non-linear eqs") {
150 double X0_old = 1.2345;
151 double X1_old = 1.2345;
152 double X2_old = 1.2345;
153 double X3_old = 1.2345;
155 void operator()(
const Eigen::Matrix<double, 4, 1>& X,
156 Eigen::Matrix<double, 4, 1>& ,
157 Eigen::Matrix<double, 4, 1>& F,
158 Eigen::Matrix<double, 4, 4>& J)
const {
159 F[0] = -(-3.0 * X[0] * X[2] * dt + X[0] - X0_old + 2.0 * dt / X[1]);
160 F[1] = -(X[1] - X1_old + dt * (4.0 * X[0] - 6.2 * X[1] + X[3]));
161 F[2] = -((X[2] * (X[2] - X2_old) - dt * (X[2] * (-1.2 * X[1] + 3.0) + 0.3)) / X[2]);
162 F[3] = -(-4.0 * X[0] * X[1] * X[2] * dt + X[3] - X3_old + 6.0 * dt / X[2]);
163 J(0, 0) = 3.0 * X[2] * dt - 1.0;
164 J(0, 1) = 2.0 * dt / std::pow(X[1], 2);
165 J(0, 2) = 3.0 * X[0] * dt;
168 J(1, 1) = 6.2 * dt - 1.0;
173 J(2, 2) = -1.0 - 0.3 * dt / std::pow(X[2], 2);
175 J(3, 0) = 4.0 * X[1] * X[2] * dt;
176 J(3, 1) = 4.0 * X[0] * X[2] * dt;
177 J(3, 2) = 4.0 * X[0] * X[1] * dt + 6.0 * dt / std::pow(X[2], 2);
181 Eigen::Matrix<double, 4, 1> X{0.21231, 0.4435, -0.11537, -0.8124312};
182 Eigen::Matrix<double, 4, 1> dX;
183 Eigen::Matrix<double, 4, 1> F;
184 Eigen::Matrix<double, 4, 4> J;
188 THEN(
"find a solution") {
189 CAPTURE(iter_newton);
191 REQUIRE(iter_newton > 0);
196 GIVEN(
"system of 5 non-linear eqs") {
198 void operator()(
const Eigen::Matrix<double, 5, 1>& X,
199 Eigen::Matrix<double, 5, 1>& ,
200 Eigen::Matrix<double, 5, 1>& F,
201 Eigen::Matrix<double, 5, 5>& J)
const {
202 F[0] = -3.0 * X[0] * X[2] + X[0] + 2.0 / X[1];
203 F[1] = 4.0 * X[0] - 5.2 * X[1] + X[3];
204 F[2] = 1.2 * X[1] + X[2] - 3.0 - 0.3 / X[2];
205 F[3] = -4.0 * X[0] * X[1] * X[2] + X[3] + 6.0 / X[2];
206 F[4] = (-4.0 * X[0] + (X[4] + cos(X[1])) * (X[1] * X[2] - X[3] * X[4])) /
207 (X[1] * X[2] - X[3] * X[4]);
208 J(0, 0) = -3.0 * X[2] + 1.0;
209 J(0, 1) = -2.0 / std::pow(X[1], 2);
210 J(0, 2) = -3.0 * X[0];
220 J(2, 2) = 1.0 + 0.3 / std::pow(X[2], 2);
223 J(3, 0) = -4.0 * X[1] * X[2];
224 J(3, 1) = -4.0 * X[0] * X[2];
225 J(3, 2) = -4.0 * X[0] * X[1] - 6.0 / std::pow(X[2], 2);
228 J(4, 0) = -4.0 / (X[1] * X[2] - X[3] * X[4]);
229 J(4, 1) = 4.0 * X[0] * X[2] / std::pow(X[1] * X[2] - X[3] * X[4], 2) -
231 J(4, 2) = 4.0 * X[0] * X[1] / std::pow(X[1] * X[2] - X[3] * X[4], 2);
232 J(4, 3) = -4.0 * X[0] * X[4] / std::pow(X[1] * X[2] - X[3] * X[4], 2);
233 J(4, 4) = -4.0 * X[0] * X[3] / std::pow(X[1] * X[2] - X[3] * X[4], 2) + 1.0;
236 Eigen::Matrix<double, 5, 1> X;
237 X << 8.234, -245.46, 123.123, 0.8343, 5.555;
238 Eigen::Matrix<double, 5, 1> dX;
239 Eigen::Matrix<double, 5, 1> F;
240 Eigen::Matrix<double, 5, 5> J;
242 int iter_newton = newton::newton_solver<5, functor>(X, fn);
244 THEN(
"find a solution") {
245 CAPTURE(iter_newton);
247 REQUIRE(iter_newton > 0);
252 GIVEN(
"system of 10 non-linear eqs") {
254 void operator()(
const Eigen::Matrix<double, 10, 1>& X,
255 Eigen::Matrix<double, 10, 1>& ,
256 Eigen::Matrix<double, 10, 1>& F,
257 Eigen::Matrix<double, 10, 10>& J)
const {
258 F[0] = -3.0 * X[0] * X[1] + X[0] + 2.0 * X[1];
259 F[1] = 4.0 * X[0] - 0.29999999999999999 * std::pow(X[1], 2) + X[1];
260 F[2] = 2.0 * X[1] + X[2] + 2.0 * X[3] * X[5] * X[7] - 3.0 * X[4] * X[8] - X[5];
261 F[3] = 4.0 * X[0] - 0.29999999999999999 * std::pow(X[1], 2) + X[3] -
263 F[4] = -3.0 * X[0] * X[7] + 2.0 * X[1] - 4.0 * X[3] * X[8] + X[4];
264 F[5] = -X[2] * X[5] * X[8] + 4.0 * X[3] - 0.29999999999999999 * X[4] * X[9] + X[5];
265 F[6] = -3.0 * X[0] * X[1] - 2.1000000000000001 * X[3] * X[4] * X[5] + X[6] +
267 F[7] = 4.0 * X[0] - 0.29999999999999999 * X[6] * X[7] + X[7];
268 F[8] = -3.0 * X[0] * X[1] - X[2] * X[3] * X[4] * std::pow(X[5], 2) + 2.0 * X[5] +
270 F[9] = -0.29999999999999999 * X[2] * X[4] + 4.0 * std::pow(X[9], 2) + X[9];
271 J(0, 0) = -3.0 * X[1] + 1.0;
272 J(0, 1) = -3.0 * X[0] + 2.0;
282 J(1, 1) = -0.59999999999999998 * X[1] + 1.0;
294 J(2, 3) = 2.0 * X[5] * X[7];
295 J(2, 4) = -3.0 * X[8];
296 J(2, 5) = 2.0 * X[3] * X[7] - 1.0;
298 J(2, 7) = 2.0 * X[3] * X[5];
299 J(2, 8) = -3.0 * X[4];
302 J(3, 1) = -0.59999999999999998 * X[1];
305 J(3, 4) = -X[6] * X[7];
307 J(3, 6) = -X[4] * X[7];
308 J(3, 7) = -X[4] * X[6];
311 J(4, 0) = -3.0 * X[7];
314 J(4, 3) = -4.0 * X[8];
318 J(4, 7) = -3.0 * X[0];
319 J(4, 8) = -4.0 * X[3];
323 J(5, 2) = -X[5] * X[8];
325 J(5, 4) = -0.29999999999999999 * X[9];
326 J(5, 5) = -X[2] * X[8] + 1.0;
329 J(5, 8) = -X[2] * X[5];
330 J(5, 9) = -0.29999999999999999 * X[4];
331 J(6, 0) = -3.0 * X[1];
332 J(6, 1) = -3.0 * X[0];
334 J(6, 3) = -2.1000000000000001 * X[4] * X[5];
335 J(6, 4) = -2.1000000000000001 * X[3] * X[5];
336 J(6, 5) = -2.1000000000000001 * X[3] * X[4];
347 J(7, 6) = -0.29999999999999999 * X[7];
348 J(7, 7) = -0.29999999999999999 * X[6] + 1.0;
351 J(8, 0) = -3.0 * X[1];
352 J(8, 1) = -3.0 * X[0];
353 J(8, 2) = -X[3] * X[4] * std::pow(X[5], 2);
354 J(8, 3) = -X[2] * X[4] * std::pow(X[5], 2);
355 J(8, 4) = -X[2] * X[3] * std::pow(X[5], 2);
356 J(8, 5) = -2.0 * X[2] * X[3] * X[4] * X[5] + 2.0;
363 J(9, 2) = -0.29999999999999999 * X[4];
365 J(9, 4) = -0.29999999999999999 * X[2];
370 J(9, 9) = 8.0 * X[9] + 1.0;
374 Eigen::Matrix<double, 10, 1> X;
375 X << 8.234, -5.46, 1.123, 0.8343, 5.555, 18.234, -2.46, 0.123, 10.8343, -4.685;
376 Eigen::Matrix<double, 10, 1> dX;
377 Eigen::Matrix<double, 10, 1> F;
378 Eigen::Matrix<double, 10, 10> J;
380 int iter_newton = newton::newton_solver<10, functor>(X, fn);
382 THEN(
"find a solution") {
383 CAPTURE(iter_newton);
385 REQUIRE(iter_newton > 0);