preCICE
Loading...
Searching...
No Matches
PreconditionerTest.cpp
Go to the documentation of this file.
1#include <Eigen/Core>
2#include <algorithm>
3#include <cstddef>
4#include <vector>
12#include "testing/Testing.hpp"
13
14BOOST_AUTO_TEST_SUITE(AccelerationTests)
15
16using namespace precice;
17using namespace precice::acceleration;
18using namespace precice::acceleration::impl;
19
21 Eigen::VectorXd _data;
22 Eigen::VectorXd _res;
23 Eigen::VectorXd _dataLargerSize;
24 Eigen::VectorXd _dataSmallerSize;
25 Eigen::VectorXd _compareDataRes;
26 Eigen::VectorXd _compareDataResSum;
27 Eigen::VectorXd _compareDataResSum2;
29 Eigen::VectorXd _compareDataResSumUpdate;
32 Eigen::VectorXd _compareDataValue;
33 Eigen::VectorXd _compareDataConstant;
34
36 {
37 _data.resize(8);
38 _data << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0;
39
40 _dataLargerSize.resize(10);
41 _dataLargerSize << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 20.0;
42
43 _dataSmallerSize.resize(6);
44 _dataSmallerSize << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0;
45
46 _res.resize(8);
47 _res << 0.1, 0.1, 0.001, 0.001, 0.001, 0.001, 10.0, 20.0;
48
49 _compareDataRes.resize(8);
50 _compareDataRes << 7.07106781186547372897e+00,
51 1.41421356237309474579e+01,
52 1.50000000000000000000e+03,
53 2.00000000000000000000e+03,
54 2.50000000000000000000e+03,
55 3.00000000000000000000e+03,
56 3.13049516849970566046e-01,
57 3.57770876399966353265e-01;
58
59 _compareDataResSum.resize(8);
60 _compareDataResSum << 7.90585229434499154877e+01,
61 1.58117045886899830975e+02,
62 1.67708453051717078779e+04,
63 2.23611270735622783832e+04,
64 2.79514088419528488885e+04,
65 3.35416906103434157558e+04,
66 3.50007001329973377324e+00,
67 4.00008001519969536020e+00;
68
69 _compareDataResSum2.resize(8);
70 _compareDataResSum2 << 1.58113093108981217938e+02,
71 3.16226186217962435876e+02,
72 4.74339279326943596971e+02,
73 4.00008000319945455914e+00,
74 5.00010000399932064141e+00,
75 6.00012000479918228280e+00,
76 7.00014000559904481236e+00,
77 8.00016000639890734192e+00;
78
80 _compareDataResSumThreshold << 7.90585229434499154877e+00,
81 1.58117045886899830975e+01,
82 1.67708453051717078779e+03,
83 2.23611270735622783832e+03,
84 2.79514088419528488885e+03,
85 3.35416906103434157558e+03,
86 3.50007001329973377324e-01,
87 4.00008001519969536020e-01;
88
90 _compareDataResSumUpdate << 1.43742768988091e+01,
91 2.87485537976182e+01,
92 3.04924460094031e+03,
93 4.06565946792041e+03,
94 5.08207433490052e+03,
95 6.09848920188062e+03,
96 0.636376366054497e+00,
97 0.727287275490854e+00;
98
100 _compareDataLargerSizeResSum << 7.90585229434499154877e+01,
101 1.58117045886899830975e+02,
102 1.67708453051717078779e+04,
103 2.23611270735622783832e+04,
104 2.79514088419528488885e+04,
105 3.35416906103434157558e+04,
106 3.50007001329973377324e+00,
107 4.00008001519969536020e+00,
108 10.0,
109 20.0;
110
112 _compareDataSmallerSizeResSum << 7.90585229434499154877e+01,
113 1.58117045886899830975e+02,
114 1.67708453051717078779e+04,
115 2.23611270735622783832e+04,
116 2.79514088419528488885e+04,
117 3.35416906103434157558e+04;
118
119 _compareDataValue.resize(8);
120 _compareDataValue << 4.47213595499957927704e-01,
121 8.94427190999915855407e-01,
122 3.23498319610315276940e-01,
123 4.31331092813753647075e-01,
124 5.39163866017192239255e-01,
125 6.46996639220630553879e-01,
126 6.58504607868518165859e-01,
127 7.52576694706877713514e-01;
128
129 _compareDataConstant.resize(8);
130 _compareDataConstant << 1.00000000000000002082e-03,
131 2.00000000000000004163e-03,
132 1.49999999999999977796e+00,
133 1.99999999999999955591e+00,
134 2.50000000000000044409e+00,
135 2.99999999999999955591e+00,
136 6.99999999999999883585e+05,
137 7.99999999999999650754e+05;
138 }
140};
141
142BOOST_FIXTURE_TEST_SUITE(ResPreconditionerTests, ResPreconditionerFixture)
143
144PRECICE_TEST_SETUP(1_rank)
145BOOST_AUTO_TEST_CASE(testResPreconditioner)
146{
147 PRECICE_TEST();
148 ResidualPreconditioner precond(-1);
149
150 precond.initialize({2, 4, 2}, {"Data0", "Data1", "Data2"});
151 Eigen::VectorXd backup = _data;
152
153 // should change
154 precond.update(false, _data, _res);
155 BOOST_TEST(precond.requireNewQR());
156 precond.newQRfulfilled();
157 precond.apply(_data);
158 BOOST_TEST(testing::equals(_data, _compareDataRes));
159 precond.revert(_data);
160 BOOST_TEST(testing::equals(_data, backup));
161
162 // should not change weights
163 precond.update(true, _data, _res * 10);
164 BOOST_TEST(not precond.requireNewQR());
165 precond.apply(_data);
166 BOOST_TEST(testing::equals(_data, _compareDataRes));
167 precond.revert(_data);
168 BOOST_TEST(testing::equals(_data, backup));
169}
170
171PRECICE_TEST_SETUP(1_rank)
172BOOST_AUTO_TEST_CASE(testResSumPreconditioner)
173{
174 PRECICE_TEST();
175 ResidualSumPreconditioner precond(-1, false);
176
177 precond.initialize({2, 4, 2}, {"Data0", "Data1", "Data2"});
178 Eigen::VectorXd backup = _data;
179
180 // should change, update twice to really test the summation
181 precond.update(false, _data, _res);
182 precond.update(false, _data, _res * 2);
183 BOOST_TEST(precond.requireNewQR());
184 precond.newQRfulfilled();
185 precond.apply(_data);
186 BOOST_TEST(testing::equals(_data, _compareDataResSum));
187
188 precond.revert(_data);
189 BOOST_TEST(testing::equals(_data, backup));
190
191 // should not change weights
192 precond.update(true, _data, _res * 10);
193 BOOST_TEST(not precond.requireNewQR());
194 precond.apply(_data);
195 BOOST_TEST(testing::equals(_data, _compareDataResSum));
196 precond.revert(_data);
197 BOOST_TEST(testing::equals(_data, backup));
198}
199
200PRECICE_TEST_SETUP(1_rank)
201BOOST_AUTO_TEST_CASE(testResSumPreconditionerUpdate)
202{
203 PRECICE_TEST();
204 ResidualSumPreconditioner precond(-1, true);
205
206 precond.initialize({2, 4, 2}, {"Data0", "Data1", "Data2"});
207 Eigen::VectorXd backup = _data;
208
209 // should change, update twice to really test the summation
210 precond.update(false, _data, _res);
211 precond.update(false, _data, _res * 2);
212 BOOST_TEST(precond.requireNewQR());
213 precond.newQRfulfilled();
214 precond.apply(_data);
215 BOOST_TEST(testing::equals(_data, _compareDataResSum));
216
217 precond.revert(_data);
218 BOOST_TEST(testing::equals(_data, backup));
219
220 // should not change weights
221 precond.update(true, _data, _res * 10);
222 BOOST_TEST(not precond.requireNewQR());
223 precond.apply(_data);
224 BOOST_TEST(testing::equals(_data, _compareDataResSum));
225 precond.revert(_data);
226 BOOST_TEST(testing::equals(_data, backup));
227
228 // New time windows stops automatic update of weights
229 precond.update(false, _data, _res * 3);
230 // New residuals are not large enough to trigger a change
231 BOOST_TEST(not precond.requireNewQR());
232 precond.apply(_data);
233 BOOST_TEST(testing::equals(_data, _compareDataResSum));
234 precond.revert(_data);
235
236 // Apply multiple preconditioners
237 for (int i = 0; i < 5; i++) {
238 precond.update(false, _data, _res * 3);
239 }
240 // New residuals are not large enough to trigger a change
241 BOOST_TEST(not precond.requireNewQR());
242 precond.apply(_data);
243 BOOST_TEST(testing::equals(_data, _compareDataResSum));
244 precond.revert(_data);
245
246 // Apply multiple preconditioners until weights change enough
247 for (int i = 0; i < 14; i++) {
248 precond.update(false, _data, _res * 3);
249 }
250 // New residuals are now large enough to trigger a change
251 BOOST_TEST(precond.requireNewQR());
252 precond.newQRfulfilled();
253 precond.apply(_data);
254 BOOST_TEST(testing::equals(_data, _compareDataResSumThreshold));
255 precond.revert(_data);
256}
257
258PRECICE_TEST_SETUP(1_rank)
259BOOST_AUTO_TEST_CASE(testValuePreconditioner)
260{
261 PRECICE_TEST();
262 ValuePreconditioner precond(-1);
263
264 precond.initialize({2, 4, 2}, {"Data0", "Data1", "Data2"});
265 Eigen::VectorXd backup = _data;
266
267 // should change, since this is the first time window
268 precond.update(false, _data, _res);
269 BOOST_TEST(precond.requireNewQR());
270 precond.newQRfulfilled();
271 precond.apply(_data);
272 BOOST_TEST(testing::equals(_data, _compareDataValue));
273 precond.revert(_data);
274 BOOST_TEST(testing::equals(_data, backup));
275
276 // now no change
277 precond.update(false, _data, _res);
278 BOOST_TEST(not precond.requireNewQR());
279 precond.apply(_data);
280 BOOST_TEST(testing::equals(_data, _compareDataValue));
281 precond.revert(_data);
282 BOOST_TEST(testing::equals(_data, backup));
283
284 // should change weights
285 precond.update(true, _data * 2, _res);
286 BOOST_TEST(precond.requireNewQR());
287 precond.newQRfulfilled();
288}
289
290PRECICE_TEST_SETUP(1_rank)
291BOOST_AUTO_TEST_CASE(testConstPreconditioner)
292{
293 PRECICE_TEST();
294 std::vector<double> factors;
295 factors.push_back(1e3);
296 factors.push_back(2.0);
297 factors.push_back(1e-5);
298
299 ConstantPreconditioner precond(factors);
300
301 precond.initialize({2, 4, 2}, {"Data0", "Data1", "Data2"}); // new weights already computed here
302 Eigen::VectorXd backup = _data;
303
304 // should have no effect
305 precond.update(false, _data, _res);
306 BOOST_TEST(not precond.requireNewQR());
307 precond.apply(_data);
308 BOOST_TEST(testing::equals(_data, _compareDataConstant));
309 precond.revert(_data);
310 BOOST_TEST(testing::equals(_data, backup));
311
312 // should not change weights
313 precond.update(true, _data, _res);
314 BOOST_TEST(not precond.requireNewQR());
315 precond.apply(_data);
316 BOOST_TEST(testing::equals(_data, _compareDataConstant));
317 precond.revert(_data);
318 BOOST_TEST(testing::equals(_data, backup));
319}
320
321PRECICE_TEST_SETUP(1_rank)
322BOOST_AUTO_TEST_CASE(testPreconditionerLargerDataSize)
323{
324 PRECICE_TEST();
325 ResidualSumPreconditioner precond(-1, false);
326
327 precond.initialize({2, 4, 2}, {"Data0", "Data1", "Data2"});
328 Eigen::VectorXd backup = _dataLargerSize;
329
330 // should change, update twice to really test the summation
331 precond.update(false, _data, _res);
332 precond.update(false, _data, _res * 2);
333 BOOST_TEST(precond.requireNewQR());
334 precond.newQRfulfilled();
335 precond.apply(_dataLargerSize); // should only scale the first 8 values
336 BOOST_TEST(testing::equals(_dataLargerSize, _compareDataLargerSizeResSum));
337
338 precond.revert(_dataLargerSize);
339 BOOST_TEST(testing::equals(_dataLargerSize, backup));
340
341 // should not change weights
342 precond.update(true, _data, _res * 10);
343 BOOST_TEST(not precond.requireNewQR());
344 precond.apply(_dataLargerSize);
345 BOOST_TEST(testing::equals(_dataLargerSize, _compareDataLargerSizeResSum));
346 precond.revert(_dataLargerSize);
347 BOOST_TEST(testing::equals(_dataLargerSize, backup));
348}
349
350PRECICE_TEST_SETUP(1_rank)
351BOOST_AUTO_TEST_CASE(testPreconditionerLargerResSize)
352{
353 PRECICE_TEST();
354 ResidualSumPreconditioner precond(-1, false);
355
356 precond.initialize({2, 4, 2}, {"Data0", "Data1", "Data2"});
357 Eigen::VectorXd backup = _dataSmallerSize;
358
359 // should change, update twice to really test the summation
360 precond.update(false, _data, _res);
361 precond.update(false, _data, _res * 2);
362 BOOST_TEST(precond.requireNewQR());
363 precond.newQRfulfilled();
364 precond.apply(_dataSmallerSize); // should only use the first 6 scaling factors
365 BOOST_TEST(testing::equals(_dataSmallerSize, _compareDataSmallerSizeResSum));
366
367 precond.revert(_dataSmallerSize);
368 BOOST_TEST(testing::equals(_dataSmallerSize, backup));
369
370 // should not change weights
371 precond.update(true, _data, _res * 10);
372 BOOST_TEST(not precond.requireNewQR());
373 precond.apply(_dataSmallerSize);
374 BOOST_TEST(testing::equals(_dataSmallerSize, _compareDataSmallerSizeResSum));
375 precond.revert(_dataSmallerSize);
376 BOOST_TEST(testing::equals(_dataSmallerSize, backup));
377}
378
379PRECICE_TEST_SETUP(1_rank)
380BOOST_AUTO_TEST_CASE(testMultilpleMeshes)
381{
382 PRECICE_TEST();
383 ResidualSumPreconditioner precond(-1, false);
384
385 precond.initialize({3, 5}, {"Data0", "Data1"});
386 Eigen::VectorXd backup = _data;
387
388 // should change
389 precond.update(false, _data, _res);
390 BOOST_TEST(precond.requireNewQR());
391 precond.newQRfulfilled();
392 precond.apply(_data);
393 BOOST_TEST(testing::equals(_data, _compareDataResSum2));
394 precond.revert(_data);
395 BOOST_TEST(testing::equals(_data, backup));
396
397 // should not change weights
398 precond.update(true, _data, _res * 10);
399 BOOST_TEST(not precond.requireNewQR());
400 precond.apply(_data);
401 BOOST_TEST(testing::equals(_data, _compareDataResSum2));
402 precond.revert(_data);
403 BOOST_TEST(testing::equals(_data, backup));
404}
405
406#ifndef PRECICE_NO_MPI
407PRECICE_TEST_SETUP(""_on(4_ranks).setupIntraComm())
408BOOST_AUTO_TEST_CASE(testParallelMatrixScaling)
409{
410 PRECICE_TEST();
411 // setup data
412 int localN = -1;
413 if (context.isPrimary()) {
414 localN = 2;
415 } else if (context.isRank(1)) {
416 localN = 1;
417 } else if (context.isRank(2)) {
418 localN = 0;
419 } else if (context.isRank(3)) {
420 localN = 1;
421 }
422
423 int globalN = 4;
424
425 Eigen::MatrixXd V(localN, 2);
426 Eigen::MatrixXd M(globalN, localN);
427 Eigen::VectorXd x(localN);
428 Eigen::MatrixXd V_back(localN, 2);
429 Eigen::MatrixXd M_back(globalN, localN);
430 Eigen::VectorXd x_back(localN);
431
432 if (context.isPrimary()) {
433 V(0, 0) = 1.0;
434 V(0, 1) = 2.0;
435 V(1, 0) = 3.0;
436 V(1, 1) = 4.0;
437 M(0, 0) = 1.0;
438 M(0, 1) = 2.0;
439 M(1, 0) = 3.0;
440 M(1, 1) = 4.0;
441 M(2, 0) = 1.0;
442 M(2, 1) = 2.0;
443 M(3, 0) = 3.0;
444 M(3, 1) = 4.0;
445 x(0) = 5.0;
446 x(1) = 5.0;
447 } else if (context.isRank(1)) {
448 V(0, 0) = 5.0;
449 V(0, 1) = 6.0;
450 M(0, 0) = 1.0;
451 M(1, 0) = 2.0;
452 M(2, 0) = 3.0;
453 M(3, 0) = 4.0;
454 x(0) = 5.0;
455 } else if (context.isRank(2)) {
456 } else if (context.isRank(3)) {
457 V(0, 0) = 7.0;
458 V(0, 1) = 8.0;
459 M(0, 0) = 1.0;
460 M(1, 0) = 2.0;
461 M(2, 0) = 3.0;
462 M(3, 0) = 4.0;
463 x(0) = 5.0;
464 }
465
466 V_back = V;
467 M_back = M;
468 x_back = x;
469
470 ValuePreconditioner precond(-1);
471 precond.initialize({static_cast<size_t>(localN)}, {"Data0"});
472 precond.update(true, x, x);
473 BOOST_TEST(precond.requireNewQR());
474
475 precond.apply(V);
476
477 BOOST_TEST(testing::equals(V, V_back * 0.1));
478
479 precond.revert(V);
480
481 BOOST_TEST(testing::equals(V, V_back));
482}
483#endif
484
BOOST_AUTO_TEST_CASE(testIQNIMVJPPWithSubsteps)
BOOST_AUTO_TEST_SUITE(PreProcess)
BOOST_AUTO_TEST_SUITE_END()
#define PRECICE_TEST()
Definition Testing.hpp:39
#define PRECICE_TEST_SETUP(...)
Creates and attaches a TestSetup to a Boost test case.
Definition Testing.hpp:29
Preconditioner that uses the constant user-defined factors to scale the quasi-Newton system.
void initialize(std::vector< size_t > svs, std::vector< std::string > svNames) override
initialize the preconditioner
void apply(Eigen::MatrixXd &M, bool transpose)
Apply preconditioner to matrix.
void revert(Eigen::MatrixXd &M, bool transpose)
Apply inverse preconditioner to matrix.
void newQRfulfilled()
to tell the preconditioner that QR-decomposition has been recomputed
void update(bool timeWindowComplete, const Eigen::VectorXd &oldValues, const Eigen::VectorXd &res)
Update the scaling after every FSI iteration and require a new QR decomposition (if necessary)
virtual void initialize(std::vector< size_t > svs, std::vector< std::string > svNames)
initialize the preconditioner
bool requireNewQR()
returns true if a QR decomposition from scratch is necessary
Preconditioner that uses the recent residual to scale the quasi-Newton system.
Preconditioner that uses the residuals of all iterations of the current time window summed up to scal...
void initialize(std::vector< size_t > svs, std::vector< std::string > svNames) override
initialize the preconditioner
Preconditioner that uses the values from the previous time window to scale the quasi-Newton system.
contains implementations of acceleration schemes.
boost::test_tools::predicate_result equals(const std::vector< float > &VectorA, const std::vector< float > &VectorB, float tolerance)
equals to be used in tests. Compares two std::vectors using a given tolerance. Prints both operands o...
Definition Testing.cpp:93
Main namespace of the precice library.
Eigen::VectorXd _compareDataSmallerSizeResSum
Eigen::VectorXd _compareDataResSumUpdate
~ResPreconditionerFixture()=default
Eigen::VectorXd _compareDataResSumThreshold
Eigen::VectorXd _compareDataLargerSizeResSum