preCICE v3.1.2
Loading...
Searching...
No Matches
BaseQNAcceleration.cpp
Go to the documentation of this file.
2#include <Eigen/Core>
3#include <boost/range/adaptor/map.hpp>
4#include <cmath>
5#include <memory>
6#include <utility>
7
10#include "com/Communication.hpp"
11#include "com/SharedPointer.hpp"
13#include "logging/LogMacros.hpp"
14#include "mesh/Mesh.hpp"
16#include "profiling/Event.hpp"
18#include "utils/Helpers.hpp"
19#include "utils/IntraComm.hpp"
20#include "utils/assertion.hpp"
21
22namespace precice {
23namespace io {
24class TXTReader;
25class TXTWriter;
26} // namespace io
27namespace acceleration {
28
29/* ----------------------------------------------------------------------------
30 * Constructor
31 * ----------------------------------------------------------------------------
32 */
34 double initialRelaxation,
35 bool forceInitialRelaxation,
36 int maxIterationsUsed,
37 int timeWindowsReused,
38 int filter,
39 double singularityLimit,
40 std::vector<int> dataIDs,
41 impl::PtrPreconditioner preconditioner)
42 : _preconditioner(std::move(preconditioner)),
43 _initialRelaxation(initialRelaxation),
44 _maxIterationsUsed(maxIterationsUsed),
45 _timeWindowsReused(timeWindowsReused),
46 _dataIDs(std::move(dataIDs)),
47 _forceInitialRelaxation(forceInitialRelaxation),
48 _qrV(filter),
49 _filter(filter),
50 _singularityLimit(singularityLimit),
51 _infostringstream(std::ostringstream::ate)
52{
54 "Initial relaxation factor for QN acceleration has to "
55 "be larger than zero and smaller or equal than one. "
56 "Current initial relaxation is {}",
59 "Maximum number of iterations used in the quasi-Newton acceleration "
60 "scheme has to be larger than zero. "
61 "Current maximum reused iterations is {}",
64 "Number of previous time windows to be reused for "
65 "quasi-Newton acceleration has to be larger than or equal to zero. "
66 "Current number of time windows reused is {}",
68}
69
77 const DataMap &cplData)
78{
79 PRECICE_TRACE(cplData.size());
80
81 for (const DataMap::value_type &pair : cplData) {
82 PRECICE_ASSERT(pair.second->getSize() == pair.second->getPreviousIterationSize(), "current and previousIteration have to be initialized and of identical size.",
83 pair.second->getSize(), pair.second->getPreviousIterationSize());
84 }
85
87 std::any_of(cplData.cbegin(), cplData.cend(), [](const auto &p) { return p.second->hasGradient(); }),
88 "Gradient data, which is required by at least one of the configured data mappings, is not yet compatible with quasi-Newton acceleration. This combination might lead to numerical issues. "
89 "Consider switching to a different acceleration scheme or a different data mapping scheme.");
90
91 checkDataIDs(cplData);
92
93 for (const auto &data : cplData | boost::adaptors::map_values) {
94 PRECICE_CHECK(!data->exchangeSubsteps(),
95 "Quasi-Newton acceleration does not yet support using data from all substeps. Please set substeps=\"false\" in the exchange tag of data \"{}\".", data->getDataName());
96 }
97
98 size_t entries = 0;
99 std::vector<size_t> subVectorSizes; // needed for preconditioner
100
101 for (auto &elem : _dataIDs) {
102 entries += cplData.at(elem)->getSize();
103 subVectorSizes.push_back(cplData.at(elem)->getSize());
104 }
105
107 _firstIteration = true;
108 _firstTimeWindow = true;
109
110 PRECICE_ASSERT(_oldXTilde.size() == 0);
111 PRECICE_ASSERT(_oldResiduals.size() == 0);
112 _oldXTilde = Eigen::VectorXd::Zero(entries);
113 _oldResiduals = Eigen::VectorXd::Zero(entries);
114 _residuals = Eigen::VectorXd::Zero(entries);
115 _values = Eigen::VectorXd::Zero(entries);
116 _oldValues = Eigen::VectorXd::Zero(entries);
117
126
127 if (entries <= 0) {
128 _hasNodesOnInterface = false;
129 }
130
137 _dimOffsets[0] = 0;
138 for (size_t i = 0; i < _dimOffsets.size() - 1; i++) {
139 int accumulatedNumberOfUnknowns = 0;
140 for (auto &elem : _dataIDs) {
141 const auto &offsets = cplData.at(elem)->getVertexOffsets();
142 accumulatedNumberOfUnknowns += offsets[i] * cplData.at(elem)->getDimensions();
143 }
144 _dimOffsets[i + 1] = accumulatedNumberOfUnknowns;
145 }
146 PRECICE_DEBUG("Number of unknowns at the interface (global): {}", _dimOffsets.back());
148 _infostringstream << fmt::format("\n--------\n DOFs (global): {}\n offsets: {}\n", _dimOffsets.back(), _dimOffsets);
149 }
150
151 // test that the computed number of unknown per proc equals the number of entries actually present on that proc
153 PRECICE_ASSERT(entries == unknowns, entries, unknowns);
154 } else {
155 _infostringstream << fmt::format("\n--------\n DOFs (global): {}\n", entries);
156 }
157
158 // set the number of global rows in the QRFactorization.
160
161 // Fetch secondary data IDs, to be relaxed with same coefficients from IQN-ILS
162 for (const DataMap::value_type &pair : cplData) {
163 if (not utils::contained(pair.first, _dataIDs)) {
164 _secondaryDataIDs.push_back(pair.first);
165 int secondaryEntries = pair.second->getSize();
166 _secondaryResiduals[pair.first] = Eigen::VectorXd::Zero(secondaryEntries);
167 }
168 }
169
170 _preconditioner->initialize(subVectorSizes);
171}
172
181 const DataMap &cplData)
182{
184
185 // Compute current residual: vertex-data - oldData
188
190 "The coupling residual equals almost zero. There is maybe something wrong in your adapter. "
191 "Maybe you always write the same data or you call advance without "
192 "providing new data first or you do not use available read data. "
193 "Or you just converge much further than actually necessary.");
194
195 // if (_firstIteration && (_firstTimeWindow || (_matrixCols.size() < 2))) {
197 // do nothing: constant relaxation
198 } else {
199 PRECICE_DEBUG(" Update Difference Matrices");
200 if (not _firstIteration) {
201 // Update matrices V, W with newest information
202
203 PRECICE_ASSERT(_matrixV.cols() == _matrixW.cols(), _matrixV.cols(), _matrixW.cols());
205
208 "The number of columns in the least squares system exceeded half the number of unknowns at the interface. "
209 "The system will probably become bad or ill-conditioned and the quasi-Newton acceleration may not "
210 "converge. Maybe the number of allowed columns (\"max-used-iterations\") should be limited.");
211
212 Eigen::VectorXd deltaR = _residuals;
213 deltaR -= _oldResiduals;
214
215 Eigen::VectorXd deltaXTilde = _values;
216 deltaXTilde -= _oldXTilde;
217
218 double residualMagnitude = utils::IntraComm::l2norm(deltaR);
219
221 residualMagnitude /= utils::IntraComm::l2norm(_values);
222 }
224 math::equals(residualMagnitude, 0.0),
225 "Adding a vector with a two-norm of {} to the quasi-Newton V matrix, which will lead to "
226 "ill-conditioning. A filter might delete the column again. Still, this could mean that you are "
227 "converging too tightly, that you reached steady-state, or that you are giving by mistake identical "
228 "data to preCICE in two consecutive iterations.",
229 residualMagnitude);
230
231 bool columnLimitReached = getLSSystemCols() == _maxIterationsUsed;
232 bool overdetermined = getLSSystemCols() <= getLSSystemRows();
233 if (not columnLimitReached && overdetermined) {
234
236 utils::appendFront(_matrixW, deltaXTilde);
237
238 // insert column deltaR = _residuals - _oldResiduals at pos. 0 (front) into the
239 // QR decomposition and update decomposition
240
241 //apply scaling here
242 _preconditioner->apply(deltaR);
243 _qrV.pushFront(deltaR);
244
245 _matrixCols.front()++;
246 } else {
248 utils::shiftSetFirst(_matrixW, deltaXTilde);
249
250 // inserts column deltaR at pos. 0 to the QR decomposition and deletes the last column
251 // the QR decomposition of V is updated
252 _preconditioner->apply(deltaR);
253 _qrV.pushFront(deltaR);
254 _qrV.popBack();
255
256 _matrixCols.front()++;
257 _matrixCols.back()--;
258 if (_matrixCols.back() == 0) {
260 }
261 _nbDropCols++;
262 }
263 }
264 _oldResiduals = _residuals; // Store residuals
265 _oldXTilde = _values; // Store x_tilde
266 }
267}
268
276 DataMap &cplData)
277{
278 PRECICE_TRACE(_dataIDs.size(), cplData.size());
279
280 profiling::Event e("cpl.computeQuasiNewtonUpdate", profiling::Synchronize);
281
282 PRECICE_ASSERT(_oldResiduals.size() == _oldXTilde.size(), _oldResiduals.size(), _oldXTilde.size());
283 PRECICE_ASSERT(_values.size() == _oldXTilde.size(), _values.size(), _oldXTilde.size());
284 PRECICE_ASSERT(_oldValues.size() == _oldXTilde.size(), _oldValues.size(), _oldXTilde.size());
285 PRECICE_ASSERT(_residuals.size() == _oldXTilde.size(), _residuals.size(), _oldXTilde.size());
286
287 // assume data structures associated with the LS system can be updated easily.
288
289 // scale data values (and secondary data values)
291
298
300 PRECICE_DEBUG(" Performing underrelaxation");
301 _oldXTilde = _values; // Store x tilde
302 _oldResiduals = _residuals; // Store current residual
303
304 // Perform constant relaxation
305 // with residual: x_new = x_old + omega * res
309
311 } else {
312 PRECICE_DEBUG(" Performing quasi-Newton Step");
313
314 // If the previous time window converged within one single iteration, nothing was added
315 // to the LS system matrices and they need to be restored from the backup at time T-2
317 PRECICE_DEBUG(" Last time window converged after one iteration. Need to restore the matrices from backup.");
318
322
323 // re-computation of QR decomposition from _matrixV = _matrixVBackup
324 // this occurs very rarely, to be precise, it occurs only if the coupling terminates
325 // after the first iteration and the matrix data from time window t-2 has to be used
328 _preconditioner->revert(_matrixV);
329 _resetLS = true; // need to recompute _Wtil, Q, R (only for IMVJ efficient update)
330 }
331
339 _preconditioner->update(false, _values, _residuals);
340 // apply scaling to V, V' := P * V (only needed to reset the QR-dec of V)
342
343 if (_preconditioner->requireNewQR()) {
344 if (not(_filter == Acceleration::QR2FILTER)) { // for QR2 filter, there is no need to do this twice
346 }
347 _preconditioner->newQRfulfilled();
348 }
349
350 if (_firstIteration) {
351 _nbDelCols = 0;
352 _nbDropCols = 0;
353 }
354
355 // apply the configured filter to the LS system
356 profiling::Event applyingFilter("ApplyFilter");
357 applyFilter();
358 applyingFilter.stop();
359
360 // revert scaling of V, in computeQNUpdate all data objects are unscaled.
361 _preconditioner->revert(_matrixV);
362
368 Eigen::VectorXd xUpdate = Eigen::VectorXd::Zero(_residuals.size());
369 computeQNUpdate(cplData, xUpdate);
370
374 _values += xUpdate;
375
376 // pending deletion: delete old V, W matrices if timeWindowsReused = 0
377 // those were only needed for the first iteration (instead of underrelax.)
379 // save current matrix data in case the coupling for the next time window will terminate
380 // after the first iteration (no new data, i.e., V = W = 0)
381 if (getLSSystemCols() > 0) {
385 }
386 // if no time windows reused, the matrix data needs to be cleared as it was only needed for the
387 // QN-step in the first iteration (idea: rather perform QN-step with information from last converged
388 // time window instead of doing a underrelaxation)
389 if (not _firstTimeWindow) {
390 _matrixV.resize(0, 0);
391 _matrixW.resize(0, 0);
393 _matrixCols.push_front(0); // vital after clear()
394 _qrV.reset();
395 // set the number of global rows in the QRFactorization.
397 _resetLS = true; // need to recompute _Wtil, Q, R (only for IMVJ efficient update)
398 }
399 }
400
403 "The quasi-Newton update contains NaN values. This means that the quasi-Newton acceleration failed to converge. "
404 "When writing your own adapter this could indicate that you give wrong information to preCICE, such as identical "
405 "data in succeeding iterations. Or you do not properly save and reload checkpoints. "
406 "If you give the correct data this could also mean that the coupled problem is too hard to solve. Try to use a QR "
407 "filter or increase its threshold (larger epsilon).");
408 }
409
410 splitCouplingData(cplData);
411 // number of iterations (usually equals number of columns in LS-system)
412 its++;
413 _firstIteration = false;
414}
415
417{
419
421 // do nothing
422 } else {
423 // do: filtering of least-squares system to maintain good conditioning
424 std::vector<int> delIndices(0);
426 // start with largest index (as V,W matrices are shrunk and shifted
427
428 for (int i = delIndices.size() - 1; i >= 0; i--) {
429
430 removeMatrixColumn(delIndices[i]);
431
432 PRECICE_DEBUG(" Filter: removing column with index {} in iteration {} of time window: {}", delIndices[i], its, tWindows);
433 }
434 PRECICE_ASSERT(_matrixV.cols() == _qrV.cols(), _matrixV.cols(), _qrV.cols());
435 }
436}
437
439 const DataMap &cplData)
440{
442
443 int offset = 0;
444 for (int id : _dataIDs) {
445 int size = cplData.at(id)->getSize();
446 auto &valuesPart = cplData.at(id)->values();
447 for (int i = 0; i < size; i++) {
448 valuesPart(i) = _values(i + offset);
449 }
450 offset += size;
451 }
452}
453
463 const DataMap &cplData)
464{
466
468 _infostringstream << "# time window " << tWindows << " converged #\n iterations: " << its
469 << "\n used cols: " << getLSSystemCols() << "\n del cols: " << _nbDelCols << '\n';
470
471 its = 0;
472 tWindows++;
473
474 // the most recent differences for the V, W matrices have not been added so far
475 // this has to be done in iterations converged, as PP won't be called any more if
476 // convergence was achieved
479
480 if (not _matrixCols.empty() && _matrixCols.front() == 0) { // Did only one iteration
482 }
483
484#ifndef NDEBUG
485 std::ostringstream stream;
486 stream << "Matrix column counters: ";
487 for (int cols : _matrixCols) {
488 stream << cols << ", ";
489 }
490 PRECICE_DEBUG(stream.str());
491#endif // Debug
492
493 // doing specialized stuff for the corresponding acceleration scheme after
494 // convergence of iteration i.e.:
495 // - analogously to the V,W matrices, remove columns from matrices for secondary data
496 // - save the old Jacobian matrix
498
499 // if we already have convergence in the first iteration of the first time window
500 // we need to do underrelaxation in the first iteration of the second time window
501 // so "_firstTimeWindow" is slightly misused, but still the best way to understand
502 // the concept
503 if (not _firstIteration)
504 _firstTimeWindow = false;
505
506 // update preconditioner depending on residuals or values (must be after specialized iterations converged --> IMVJ)
507 _preconditioner->update(true, _values, _residuals);
508
509 if (_timeWindowsReused == 0) {
511 _matrixV.resize(0, 0);
512 _matrixW.resize(0, 0);
513 _qrV.reset();
514 // set the number of global rows in the QRFactorization.
516 _matrixCols.clear(); // _matrixCols.push_front() at the end of the method.
517 } else {
523 }
524 } else if (static_cast<int>(_matrixCols.size()) > _timeWindowsReused) {
525 int toRemove = _matrixCols.back();
526 _nbDropCols += toRemove;
527 PRECICE_ASSERT(toRemove > 0, toRemove);
528 PRECICE_DEBUG("Removing {} cols from least-squares system with {} cols", toRemove, getLSSystemCols());
529 PRECICE_ASSERT(_matrixV.cols() == _matrixW.cols(), _matrixV.cols(), _matrixW.cols());
530 PRECICE_ASSERT(getLSSystemCols() > toRemove, getLSSystemCols(), toRemove);
531
532 // remove columns
533 for (int i = 0; i < toRemove; i++) {
536 // also remove the corresponding columns from the dynamic QR-descomposition of _matrixV
537 _qrV.popBack();
538 }
540 }
541
543 _firstIteration = true;
544}
545
553 int columnIndex)
554{
555 PRECICE_TRACE(columnIndex, _matrixV.cols());
556
557 _nbDelCols++;
558
559 PRECICE_ASSERT(_matrixV.cols() > 1);
562
563 // Reduce column count
564 std::deque<int>::iterator iter = _matrixCols.begin();
565 int cols = 0;
566 while (iter != _matrixCols.end()) {
567 cols += *iter;
568 if (cols > columnIndex) {
569 PRECICE_ASSERT(*iter > 0);
570 *iter -= 1;
571 if (*iter == 0) {
572 _matrixCols.erase(iter);
573 }
574 break;
575 }
576 iter++;
577 }
578}
579
584
589
591{
592 return _nbDelCols;
593}
594
596{
597 return _nbDropCols;
598}
599
601{
602 int cols = 0;
603 for (int col : _matrixCols) {
604 cols += col;
605 }
607 PRECICE_ASSERT(cols == _matrixV.cols(), cols, _matrixV.cols(), _matrixCols, _qrV.cols());
608 PRECICE_ASSERT(cols == _matrixW.cols(), cols, _matrixW.cols());
609 }
610
611 return cols;
612}
613
615{
617 return _dimOffsets.back();
618 }
619 return _residuals.size();
620}
621
623 const std::string &s, bool allProcs)
624{
626 // serial acceleration mode
628
629 // parallel acceleration
630 } else {
631 if (not allProcs) {
634 } else {
636 }
637 }
639}
640} // namespace acceleration
641} // namespace precice
#define PRECICE_WARN_IF(condition,...)
Definition LogMacros.hpp:21
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:64
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:95
#define PRECICE_CHECK(check,...)
Definition LogMacros.hpp:35
T any_of(T... args)
#define PRECICE_ASSERT(...)
Definition assertion.hpp:87
T at(T... args)
T back(T... args)
T cbegin(T... args)
void checkDataIDs(const DataMap &cplData) const
Checks if all dataIDs are contained in cplData.
void concatenateCouplingData(const DataMap &cplData, const std::vector< DataID > &dataIDs, Eigen::VectorXd &targetValues, Eigen::VectorXd &targetOldValues) const
Concatenates all coupling data involved into a single vector.
virtual void updateDifferenceMatrices(const DataMap &cplData)
Updates the V, W matrices (as well as the matrices for the secondary data)
Eigen::VectorXd _oldResiduals
Difference between solver input and output from last time window.
int _filter
filter method that is used to maintain good conditioning of the least-squares system Either of two ty...
double _initialRelaxation
Constant relaxation factor used for first iteration.
int _timeWindowsReused
Maximum number of old time windows (with data values) kept.
virtual int getLSSystemCols() const
: computes number of cols in least squares system, i.e, number of cols in _matrixV,...
int _nbDelCols
Number of filtered out columns in this time window.
virtual void specializedIterationsConverged(const DataMap &cplData)=0
Marks a iteration sequence as converged.
virtual void applyFilter()
Applies the filter method for the least-squares system, defined in the configuration.
virtual void iterationsConverged(const DataMap &cplData)
Marks a iteration sequence as converged.
Eigen::VectorXd _oldValues
Concatenation of all (old) coupling data involved in the QN system.
Eigen::MatrixXd _matrixVBackup
backup of the V,W and matrixCols data structures. Needed for the skipping of initial relaxation,...
Eigen::VectorXd _oldXTilde
Solver output from last iteration.
std::ostringstream _infostringstream
write some debug/acceleration info to file
bool _resetLS
If true, the LS system has been modified (reset or recomputed) in such a way, that mere updating of m...
BaseQNAcceleration(double initialRelaxation, bool forceInitialRelaxation, int maxIterationsUsed, int timeWindowsReused, int filter, double singularityLimit, std::vector< int > dataIDs, impl::PtrPreconditioner preconditioner)
int _nbDropCols
Number of dropped columns in this time window (old time window out of scope)
virtual int getDroppedColumns() const
how many QN columns were dropped (went out of scope) in this time window
virtual void computeQNUpdate(const DataMap &cplData, Eigen::VectorXd &xUpdate)=0
Computes the quasi-Newton update using the specified pp scheme (IQNIMVJ, IQNILS)
Eigen::MatrixXd _matrixV
Stores residual deltas.
std::vector< int > _dimOffsets
Stores the local dimensions, i.e., the offsets in _invJacobian for all processors.
virtual void exportState(io::TXTWriter &writer)
Exports the current state of the acceleration to a file.
Eigen::VectorXd _residuals
Current iteration residuals of IQN data. Temporary.
virtual void importState(io::TXTReader &reader)
Imports the last exported state of the acceleration from file.
virtual void removeMatrixColumn(int columnIndex)
Removes one iteration from V,W matrices and adapts _matrixCols.
Eigen::MatrixXd _matrixW
Stores x tilde deltas, where x tilde are values computed by solvers.
Eigen::VectorXd _values
Concatenation of all coupling data involved in the QN system.
virtual void splitCouplingData(const DataMap &cplData)
Splits up QN system vector back into the coupling data.
virtual void performAcceleration(DataMap &cplData)
Performs one acceleration step.
double _singularityLimit
Determines sensitivity when two matrix columns are considered equal.
void writeInfo(const std::string &s, bool allProcs=false)
Wwrites info to the _infostream (also in parallel)
std::deque< int > _matrixCols
Indices (of columns in W, V matrices) of 1st iterations of time windows.
bool _firstIteration
Indicates the first iteration, where constant relaxation is used.
virtual int getDeletedColumns() const
how many QN columns were deleted in this time window
std::map< int, Eigen::VectorXd > _secondaryResiduals
Current iteration residuals of secondary data.
impl::PtrPreconditioner _preconditioner
Preconditioner for least-squares system if vectorial system is used.
impl::QRFactorization _qrV
Stores the current QR decomposition ov _matrixV, can be updated via deletion/insertion of columns.
int _maxIterationsUsed
Maximum number of old data iterations kept.
virtual void computeUnderrelaxationSecondaryData(const DataMap &cplData)=0
Computes underrelaxation for the secondary data.
std::vector< int > _secondaryDataIDs
Data IDs of data not involved in IQN coefficient computation.
std::vector< int > _dataIDs
Data IDs of data to be involved in the IQN algorithm.
virtual void initialize(const DataMap &cplData)
Initializes the acceleration.
void applyFilter(double singularityLimit, std::vector< int > &delIndices, Eigen::MatrixXd &V)
filters the least squares system, i.e., the decomposition Q*R = V according to the defined filter tec...
void reset()
resets the QR factorization zo zero Q(0:0, 0:0)R(0:0, 0:0)
void popBack()
deletes the column at position _cols-1, i.e., deletes the last column and updates the QR factorizatio...
void pushFront(const Eigen::VectorXd &v)
inserts a new column at position 0, i.e., shifts right and inserts at first position and updates the ...
File reader for matrix/vector in Matlab V7 ASCII format.
Definition TXTReader.hpp:16
File writer for matrix in Matlab V7 ASCII format.
Definition TXTWriter.hpp:14
void stop()
Stops a running event.
Definition Event.cpp:37
static int getSize()
Number of ranks. This includes ranks from both participants, e.g. minimal size is 2.
Definition IntraComm.cpp:47
static double l2norm(const Eigen::VectorXd &vec)
The l2 norm of a vector is calculated on distributed data.
Definition IntraComm.cpp:67
static Rank getRank()
Current rank.
Definition IntraComm.cpp:42
static bool isPrimary()
True if this process is running the primary rank.
Definition IntraComm.cpp:52
static bool isParallel()
True if this process is running in parallel.
Definition IntraComm.cpp:62
static com::PtrCommunication & getCommunication()
Intra-participant communication.
Definition IntraComm.hpp:31
T clear(T... args)
T empty(T... args)
T cend(T... args)
T erase(T... args)
T flush(T... args)
T front(T... args)
T isnan(T... args)
constexpr bool equals(const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, double tolerance=NUMERICAL_ZERO_DIFFERENCE)
Compares two Eigen::MatrixBase for equality up to tolerance.
static constexpr SynchronizeTag Synchronize
Convenience instance of the SynchronizeTag.
Definition Event.hpp:21
void removeColumnFromMatrix(Eigen::MatrixXd &A, int col)
bool contained(const ELEMENT_T &element, const std::vector< ELEMENT_T > &vec)
Returns true, if given element is in vector, otherwise false.
Definition Helpers.hpp:39
void appendFront(Eigen::MatrixXd &A, Eigen::VectorXd &v)
void shiftSetFirst(Eigen::MatrixXd &A, const Eigen::VectorXd &v)
Main namespace of the precice library.
STL namespace.
T pop_back(T... args)
T pop_front(T... args)
T push_back(T... args)
T push_front(T... args)
T resize(T... args)
T size(T... args)
T str(T... args)