3#include <boost/range/adaptor/map.hpp>
38 double timeWindowSize,
57 "Maximum time has to be larger than zero.");
59 "Maximum number of time windows has to be larger than zero.");
61 "Time window size has to be larger than zero.");
64 "Time window size has to be given when the fixed time window size method is used.");
77 "Minimal iteration limit has to be larger than zero.");
80 "Maximal iteration limit has to be larger than zero or -1 (unlimited).");
82 "Minimal iteration limit has to be smaller equal compared to the maximal iteration limit.");
107 m2n->send(
static_cast<int>(times.
size()));
120 for (
const auto &data :
sendData | boost::adaptors::map_values) {
121 if (data->exchangeSubsteps()) {
122 const auto &stamples = data->stamples();
125 int nTimeSteps = data->timeStepsStorage().nTimes();
127 const auto timesAscending = data->timeStepsStorage().getTimes();
133 m2n->send(serialized.values(), data->getMeshID(), data->getDimensions() * serialized.nTimeSteps());
135 if (data->hasGradient()) {
136 m2n->send(serialized.gradients(), data->getMeshID(), data->getDimensions() * data->meshDimensions() * serialized.nTimeSteps());
139 const auto &sample = data->timeStepsStorage().getSampleAtEnd();
140 if (data->hasGradient()) {
142 m2n->send(sample.values, data->getMeshID(), data->getDimensions());
143 m2n->send(sample.gradients, data->getMeshID(), data->getDimensions() * data->meshDimensions());
146 m2n->send(sample.values, data->getMeshID(), data->getDimensions());
156 int numberOfTimeSteps;
157 m2n->receive(numberOfTimeSteps);
173 for (
const auto &data :
receiveData | boost::adaptors::map_values) {
175 if (data->exchangeSubsteps()) {
177 const auto nTimeSteps = timesAscending.size();
182 m2n->receive(serialized.values(), data->getMeshID(), data->getDimensions() * nTimeSteps);
184 if (data->hasGradient()) {
185 m2n->receive(serialized.gradients(), data->getMeshID(), data->getDimensions() * data->meshDimensions() * nTimeSteps);
188 serialized.deserializeInto(timesAscending, *data);
190 if (data->hasGradient()) {
192 time::Sample recvSample(data->getDimensions(), data->nVertices(), data->meshDimensions());
193 m2n->receive(recvSample.
values, data->getMeshID(), data->getDimensions());
194 m2n->receive(recvSample.
gradients, data->getMeshID(), data->getDimensions() * data->meshDimensions());
195 data->setSampleAtTime(
getTime(), recvSample);
198 time::Sample recvSample(data->getDimensions(), data->nVertices());
199 m2n->receive(recvSample.
values, data->getMeshID(), data->getDimensions());
200 data->setSampleAtTime(
getTime(), recvSample);
221 for (
const auto &data :
receiveData | boost::adaptors::map_values) {
222 PRECICE_DEBUG(
"Initialize {} as zero.", data->getDataName());
224 data->initializeWithZeroAtTime(
getTime());
230 const DataID id = data->getID();
242 "Data \"{0}\" cannot be added for sending and for receiving. Please remove either <exchange data=\"{0}\" ... /> tag", data->getName());
244 "Data \"{0}\" cannot be received from multiple sources. Please remove either <exchange data=\"{0}\" ... /> tag", data->getName());
245 PRECICE_CHECK(existing->exchangeSubsteps() == communicateSubsteps,
246 "Data \"{0}\" is configured with substeps enabled and disabled at the same time. Please make the configuration consistent in the <exchange data=\"{0}\" ... substeps=\"True/False\" ... /> tags", data->getName());
247 PRECICE_CHECK(existing->requiresInitialization == requiresInitialization,
248 "Data \"{0}\" is configured with data initialization enabled and disabled at the same time. Please make the configuration consistent in the <exchange data=\"{0}\" ... /> tags", data->getName());
296 PRECICE_WARN_IF((qnAcceleration->getMaxUsedTimeWindows() == 0) && (qnAcceleration->getMaxUsedIterations() >
_maxIterations),
"The maximum number of iterations used in the quasi-Newton acceleration scheme is greater than the maximum number of iterations allowed in one time window. When time-windows-reused is set to 0, and therefore no previous time windows are reused, the actual max-used-ietrations is equal to max-iterations.");
316 for (
const auto &data :
_allData | boost::adaptors::map_values) {
318 data->reinitialize();
418 _time.resetProgress();
427 for (
auto &data :
_allData | boost::adaptors::map_values) {
428 data->moveToNextWindow();
461 "advance() was called with the max value of double which is not allowed. "
462 "As this participant prescribes the time-window size using <time-window-size method=\"first-participant\" />, directly using getMaxTimeStepSize() is not permitted. "
463 "Make sure to pass your own desired time-step size or use the recommended limiting \"dt = min(solver_dt, getMaxTimeStepSize())\".");
469 "The time step size given to preCICE in \"advance\" {} exceeds the maximum allowed time step size {} "
470 "in the remaining of this time window. "
471 "Did you restrict your time step size, \"dt = min(preciceDt, solverDt)\"? "
472 "For more information, consult the adapter example in the preCICE documentation.",
476 _time.progressBy(timeToAdd);
482 double lastSolverTimeStepSize)
const
501 PRECICE_ASSERT(not
_hasDataBeenReceived,
"notifyDataHasBeenReceived() may only be called once within one coupling iteration. If this assertion is triggered this probably means that your coupling scheme has a bug.");
522 return _time.windowStart();
527 return _time.windowProgress();
544 return _time.untilEnd();
551 return timestepsLeft && !
_time.reachedEnd();
587 return fmt::format(
"Reached end at: final time-window: {}, final time: {}", (
_timeWindows - 1),
getTime());
596 if (hasMax && hasMin) {
611 fmt::format_to(out,
", t {}",
getTime());
613 fmt::format_to(out,
" (max: {})",
_maxTime);
625 "Data was not initialized. Did you forget to call \"requiresWritingData()\"?");
628 "The iteration checkpoint wasn't read. Did you forget to call \"requiresReadingCheckpoint()\"?");
631 "The iteration checkpoint wasn't written. Did you forget to call \"requiresWritingCheckpoint()\"?");
640 for (
const auto &data :
_allData | boost::adaptors::map_values) {
642 PRECICE_ASSERT(!data->stamples().empty(),
"initializeReceiveDataStorage() didn't initialize data correctly");
645 "Data {0} on mesh {1} doesn't contain any samples while initializing a coupling scheme of participant {2}. "
646 "There are two common configuration issues that may cause this. "
647 "Either, make sure participant {2} specifies data {0} to be written using tag <write-data mesh=\"{1}\" data=\"{0}\"/>. "
648 "Or ensure participant {2} defines a mapping to mesh {1} from a mesh using data {0}.",
671 convMeasure.measure->newMeasurementSeries();
685 convMeasure.
strict = strict;
686 convMeasure.
measure = std::move(measure);
706 bool allConverged =
true;
707 bool oneSuffices =
false;
708 bool oneStrict =
false;
714 PRECICE_ASSERT(convMeasure.couplingData->previousIteration().size() == convMeasure.couplingData->values().size(), convMeasure.couplingData->previousIteration().size(), convMeasure.couplingData->values().size(), convMeasure.couplingData->getDataName());
715 convMeasure.measure->measure(convMeasure.couplingData->previousIteration(), convMeasure.couplingData->values());
718 _convergenceWriter->writeData(convMeasure.logHeader(), convMeasure.measure->getNormResidual());
721 if (not convMeasure.measure->isConvergence()) {
722 allConverged =
false;
723 if (convMeasure.strict) {
727 "The strict convergence measure for data \"" + convMeasure.couplingData->getDataName() +
728 "\" did not converge within the maximum allowed iterations, which terminates the simulation. "
729 "To avoid this forced termination do not mark the convergence measure as strict.");
731 }
else if (convMeasure.suffices ==
true) {
735 PRECICE_INFO(convMeasure.measure->printState(convMeasure.couplingData->getDataName()));
739 if (not reachedMinIterations) {
740 messageSuffix =
" but hasn't yet reached minimal amount of iterations";
744 }
else if (oneSuffices && not oneStrict) {
745 PRECICE_INFO(
"Sufficient measures converged{}", messageSuffix);
748 return reachedMinIterations && (allConverged || (oneSuffices && not oneStrict));
795 if (qnAcceleration) {
798 _iterationsWriter->writeData(
"DeletedQNColumns", qnAcceleration->getDeletedColumns());
799 _iterationsWriter->writeData(
"DroppedQNColumns", qnAcceleration->getDroppedColumns());
823 for (
const auto &data :
_allData | boost::adaptors::map_values) {
825 "Data {0} on mesh {1} didn't contain any samples while attempting to send it to the coupling partner. "
826 "Make sure participant {2} specifies data {0} to be written using tag <write-data mesh=\"{1}\" data=\"{0}\"/>. "
827 "Alternatively, ensure participant {2} defines a mapping to mesh {1} from a mesh using data {0}.",
829 data->storeIteration();
851 [](
auto const &map) { return map.second->requiresInitialization; });
856 PRECICE_DEBUG(
"measure convergence of the coupling iteration");
896 return _time.windowStart();
911 for (
auto cpldata :
_allData | boost::adaptors::map_values) {
927 for (
auto cpldata :
_allData | boost::adaptors::map_values) {
929 idata.
add(cpldata->getDataID(),
false);
#define PRECICE_WARN_IF(condition,...)
#define PRECICE_DEBUG(...)
#define PRECICE_TRACE(...)
#define PRECICE_INFO(...)
#define PRECICE_CHECK(check,...)
#define PRECICE_ASSERT(...)
T back_inserter(T... args)
static SerializedStamples serialize(const cplscheme::CouplingData &data)
Serializes a given CouplingData into SerializedStamples.
static SerializedStamples empty(int nTimeSteps, const cplscheme::CouplingData &data)
Create SerializedStamples with allocated buffers according to size of CouplingData.
bool hasTimeWindowSize() const final override
Function to check whether time window size is defined by coupling scheme.
std::set< Action > _fulfilledActions
void initializeWithZeroInitialData(const DataMap &receiveData)
Initializes storage in receiveData as zero.
std::string printCouplingState() const override
Returns coupling state information.
bool isCouplingOngoing() const final override
Returns true, when the coupled simulation is still ongoing.
ChangedMeshes secondSynchronization() final override
void setTimeWindowSize(double timeWindowSize)
Setter for _timeWindowSize.
std::vector< ConvergenceMeasureContext > _convergenceMeasures
All convergence measures of coupling iterations.
void determineInitialReceive(DataMap &receiveData)
Sets _receivesInitializedData, if receiveData requires initialization.
bool addComputedTime(double timeToAdd) final override
Adds newly computed time. Has to be called before every advance.
void sendTimes(const m2n::PtrM2N &m2n, precice::span< double const > times)
std::string _localParticipant
Local participant name.
double _timeWindowSize
size of time window; _timeWindowSize <= _maxTime
double getNextTimeStepMaxSize() const final override
Returns the maximal size of the next time step to be computed.
void determineInitialSend(DataMap &sendData)
Sets _sendsInitializedData, if sendData requires initialization.
bool isTimeWindowComplete() const final override
Returns true, when the accessor can advance to the next time window.
virtual void exchangeSecondData()=0
Exchanges the second set of data.
void reinitialize() final override
Reinitializes the coupling scheme, coupling data, and acceleration schemes.
void receiveDataForWindowEnd(const m2n::PtrM2N &m2n, const DataMap &receiveData)
Like receiveData, but temporarily sets window time to end of window.
bool _hasDataBeenReceived
True, if data has been received from other participant. Flag is used to make sure that coupling schem...
void notifyDataHasBeenReceived()
Used to set flag after data has been received using receiveData().
bool _isInitialized
True, if coupling has been initialized.
bool isExplicitCouplingScheme() const
Function to determine whether coupling scheme is an explicit coupling scheme.
int _maxIterations
Limit of iterations during one time window. Continue to next time window, if _iterations == _maxItera...
void sendData(const m2n::PtrM2N &m2n, const DataMap &sendData)
Sends data sendDataIDs given in mapCouplingData with communication.
virtual void exchangeFirstData()=0
Functions needed for advance()
bool _doesFirstStep
True, if local participant is the one starting the explicit scheme.
bool _receivesInitializedData
True, if this participant has to receive initialized data.
void storeIteration()
used for storing all Data at end of doImplicitStep for later reference.
void initializeTXTWriters()
Initialize txt writers for iterations and convergence tracking.
ChangedMeshes firstSynchronization(const ChangedMeshes &changes) final override
bool isImplicitCouplingScheme() const override
Function to determine whether coupling scheme is an implicit coupling scheme.
bool _hasConverged
True if implicit scheme converged.
void setTimeWindows(int timeWindows)
Setter for _timeWindows.
void sendConvergence(const m2n::PtrM2N &m2n)
sends convergence to other participant via m2n
int _minIterations
Lower limit of iterations during one time window. Prevents convergence if _iterations < _minIteration...
double getTimeWindowSize() const final override
Returns the time window size, if one is given by the coupling scheme.
impl::TimeHandler _time
Time handler.
bool _sendsInitializedData
True, if this participant has to send initialized data.
bool _isTimeWindowComplete
True, if _time == _timeWindowStartTime + _timeWindowSize and (coupling has converged or _iterations =...
int _totalIterations
Number of total iterations performed.
bool anyDataRequiresInitialization(DataMap &dataMap) const
Checks whether any CouplingData in dataMap requires initialization.
bool hasConverged() const override
Checks if the implicit cplscheme has converged.
std::shared_ptr< io::TXTTableWriter > _convergenceWriter
Writes out coupling convergence within all time windows.
double _maxTime
Maximum time being computed. End of simulation is reached, if getTime() == _maxTime.
void finalize() final override
Finalizes the coupling scheme.
std::vector< double > receiveTimes(const m2n::PtrM2N &m2n)
void setAcceleration(const acceleration::PtrAcceleration &acceleration)
Set an acceleration technique.
bool reachedEndOfTimeWindow() const
Function to check whether end of time window is reached. Does not check for convergence.
bool hasDataBeenReceived() const final override
getter for _hasDataBeenReceived
bool requiresSubsteps() const final override
Returns true if any send data of the scheme requires substeps.
void moveToNextWindow()
finalizes this window's data and initializes data for next window.
void addConvergenceMeasure(int dataID, bool suffices, bool strict, impl::PtrConvergenceMeasure measure)
Adds a measure to determine the convergence of coupling iterations.
int _maxTimeWindows
Number of time windows that have to be computed. End of simulation is reached, if _timeWindows == _ma...
void doImplicitStep()
perform a coupling iteration
double getTime() const final override
getter for _time
bool receivesInitializedData() const
Getter for _receivesInitializedData.
void requireAction(Action action) final override
Sets an action required to be performed by the accessor.
int getTimeWindows() const final override
getter for _timeWindows
double getTimeWindowProgress() const
bool isInitialized() const final override
getter for _isInitialized
ImplicitData implicitDataToReceive() const override
Returns a vector of implicit data to receive in the next advance.
bool sendsInitializedData() const final override
Getter for _sendsInitializedData.
PtrCouplingData addCouplingData(const mesh::PtrData &data, mesh::PtrMesh mesh, bool requiresInitialization, bool exchangeSubsteps, CouplingData::Direction direction)
Adds CouplingData with given properties to this BaseCouplingScheme and returns a pointer to the Coupl...
double getWindowStartTime() const
int _timeWindows
number of completed time windows; _timeWindows <= _maxTimeWindows
void initialize() final override
Initializes the coupling scheme and establishes a communication connection to the coupling partner....
void markActionFulfilled(Action action) final override
Tells the coupling scheme that the accessor has performed the given action.
void advanceTXTWriters()
Advance txt writers for iterations and convergence tracking.
acceleration::PtrAcceleration _acceleration
Acceleration method to speedup iteration convergence.
double getWindowEndTime() const
bool willDataBeExchanged(double lastSolverTimeStepSize) const final override
Returns true, if data will be exchanged when calling advance().
virtual DataMap & getAccelerationData()=0
interface to provide accelerated data, depending on coupling scheme being used
double getNextTimeWindowSize() const
Getter for _nextTimeWindowSize.
double _nextTimeWindowSize
time window size of next window (acts as buffer for time windows size provided by first participant,...
DataMap _allData
All send and receive data as a map "data ID -> data".
void checkCouplingDataAvailable()
Issues an error if coupling data does not contain stamples.
CouplingMode _couplingMode
Coupling mode used by coupling scheme.
bool isActionRequired(Action action) const final override
Returns true, if the given action has to be performed by the accessor.
std::string localParticipant() const final override
Returns the name of the local participant.
void receiveConvergence(const m2n::PtrM2N &m2n)
receives convergence from other participant via m2n
void firstExchange() final override
void setNextTimeWindowSize(double timeWindowSize)
Setter for _nextTimeWindowSize.
std::shared_ptr< io::TXTTableWriter > _iterationsWriter
Responsible for monitoring iteration count over time window.
bool isActionFulfilled(Action action) const final override
Returns true, if the given action has to be performed by the accessor.
virtual void exchangeInitialData()=0
implements functionality for initialize in base class.
int _iterations
Number of iterations in current time window. _iterations <= _maxIterations.
virtual void initializeReceiveDataStorage()=0
Functions needed for initialize()
void secondExchange() final override
void newConvergenceMeasurements()
Reset all convergence measurements after convergence.
BaseCouplingScheme(double maxTime, int maxTimeWindows, double timeWindowSize, std::string localParticipant, int minIterations, int maxIterations, CouplingMode cplMode, constants::TimesteppingMethod dtMethod)
void setDoesFirstStep(bool doesFirstStep)
Setter for _doesFirstStep.
bool measureConvergence()
Measure whether coupling scheme has converged or not.
void receiveData(const m2n::PtrM2N &m2n, const DataMap &receiveData)
Receives data receiveDataIDs given in mapCouplingData with communication.
void checkCompletenessRequiredActions()
If any required actions are open, an error message is issued.
bool doesFirstStep() const
Getter for _doesFirstStep.
std::set< Action > _requiredActions
double getTimeWindowStart() const final override
static const int INFINITE_MAX_ITERATIONS
To be used, when the number of max iterations is infinite (for implicit coupling).
std::vector< MeshID > ChangedMeshes
Action
Actions that are required by CouplingSchemes.
@ WriteCheckpoint
Is the participant required to write a checkpoint?
@ ReadCheckpoint
Is the participant required to read a previously written checkpoint?
@ InitializeData
Is the initialization of coupling data required?
static const double UNDEFINED_MAX_TIME
Does not define a time limit for the coupled simulation.
static const int UNDEFINED_MIN_ITERATIONS
To be used, when the number of min iterations is not defined (for explicit coupling).
static const int UNDEFINED_MAX_ITERATIONS
To be used, when the number of max iterations is not defined (for explicit coupling).
static const double UNDEFINED_TIME_WINDOW_SIZE
To be used, when the time window size is determined dynamically during the coupling.
static const int UNDEFINED_TIME_WINDOWS
Does not define limit on time windows for the coupled simulation.
A C++ 11 implementation of the non-owning C++20 std::span type.
constexpr size_type size() const noexcept
static bool isSecondary()
True if this process is running a secondary rank.
contains implementations of acceleration schemes.
std::shared_ptr< Acceleration > PtrAcceleration
contains actions to modify exchanged data.
std::shared_ptr< ConvergenceMeasure > PtrConvergenceMeasure
contains implementations of coupling schemes for coupled simulations.
std::shared_ptr< CouplingData > PtrCouplingData
std::map< int, PtrCouplingData > DataMap
contains the logic of the parallel communication between participants.
std::shared_ptr< M2N > PtrM2N
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.
std::enable_if< std::is_arithmetic< Scalar >::value, bool >::type greaterEquals(Scalar A, Scalar B, Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
std::enable_if< std::is_arithmetic< Scalar >::value, bool >::type greater(Scalar A, Scalar B, Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
provides Mesh, Data and primitives.
std::shared_ptr< Data > PtrData
std::shared_ptr< Mesh > PtrMesh
static constexpr Group Fundamental
Convenience instance of the Cat::Fundamental.
T dynamic_pointer_cast(T... args)
Holds meta information to perform a convergence measurement.
impl::PtrConvergenceMeasure measure
PtrCouplingData couplingData
void add(DataID did, bool toKeep)
Eigen::MatrixXd gradients
The gradients of the data. Use gradients.col(d*i+k) to get the gradient of vertex i,...