3#include <boost/range/adaptor/map.hpp>
36 double timeWindowSize,
42 : _couplingMode(cplMode),
44 _maxTimeWindows(maxTimeWindows),
46 _timeWindowSize(timeWindowSize),
47 _nextTimeWindowSize(timeWindowSize),
48 _minIterations(minIterations),
49 _maxIterations(maxIterations),
52 _localParticipant(
std::move(localParticipant))
55 "Maximum time has to be larger than zero.");
57 "Maximum number of time windows has to be larger than zero.");
59 "Time window size has to be larger than zero.");
62 "Time window size has to be given when the fixed time window size method is used.");
75 "Minimal iteration limit has to be larger than zero.");
78 "Maximal iteration limit has to be larger than zero or -1 (unlimited).");
80 "Minimal iteration limit has to be smaller equal compared to the maximal iteration limit.");
104 PRECICE_DEBUG(
"Sending number or time steps {}...", numberOfTimeSteps);
105 m2n->send(numberOfTimeSteps);
121 for (
const auto &data :
sendData | boost::adaptors::map_values) {
122 const auto &stamples = data->stamples();
125 int nTimeSteps = data->timeStepsStorage().nTimes();
128 if (data->exchangeSubsteps()) {
129 const Eigen::VectorXd timesAscending = data->timeStepsStorage().getTimes();
136 m2n->send(serialized.values(), data->getMeshID(), data->getDimensions() * serialized.nTimeSteps());
138 if (data->hasGradient()) {
139 m2n->send(serialized.gradients(), data->getMeshID(), data->getDimensions() * data->meshDimensions() * serialized.nTimeSteps());
142 data->sample() = stamples.back().sample;
145 m2n->send(data->values(), data->getMeshID(), data->getDimensions());
147 if (data->hasGradient()) {
149 m2n->send(data->gradients(), data->getMeshID(), data->getDimensions() * data->meshDimensions());
159 int numberOfTimeSteps;
160 m2n->receive(numberOfTimeSteps);
161 return numberOfTimeSteps;
168 Eigen::VectorXd times(nTimeSteps);
179 for (
const auto &data :
receiveData | boost::adaptors::map_values) {
181 if (data->exchangeSubsteps()) {
184 Eigen::VectorXd serializedValues(nTimeSteps * data->getSize());
186 const Eigen::VectorXd timesAscending =
receiveTimes(m2n, nTimeSteps);
191 m2n->receive(serialized.values(), data->getMeshID(), data->getDimensions() * nTimeSteps);
193 if (data->hasGradient()) {
194 m2n->receive(serialized.gradients(), data->getMeshID(), data->getDimensions() * data->meshDimensions() * nTimeSteps);
197 serialized.deserializeInto(timesAscending, data);
200 m2n->receive(data->values(), data->getMeshID(), data->getDimensions());
202 if (data->hasGradient()) {
204 m2n->receive(data->gradients(), data->getMeshID(), data->getDimensions() * data->meshDimensions());
206 data->setSampleAtTime(
getTime(), data->sample());
226 for (
const auto &data :
receiveData | boost::adaptors::map_values) {
227 PRECICE_DEBUG(
"Initialize {} as zero.", data->getDataName());
229 data->setSampleAtTime(
getTime(), data->sample());
235 int id = data->getID();
238 ptrCplData = std::make_shared<CouplingData>(data, std::move(mesh), requiresInitialization, communicateSubsteps, direction);
242 PRECICE_CHECK(ptrCplData->getDirection() == direction,
"Data \"{0}\" cannot be added for sending and for receiving. Please remove either <exchange data=\"{0}\" ... /> tag", data->getName());
397 for (
auto &data :
_allData | boost::adaptors::map_values) {
398 data->moveToNextWindow();
432 "The time step size given to preCICE in \"advance\" {} exceeds the maximum allowed time step size {} "
433 "in the remaining of this time window. "
434 "Did you restrict your time step size, \"dt = min(preciceDt, solverDt)\"? "
435 "For more information, consult the adapter example in the preCICE documentation.",
445 double lastSolverTimeStepSize)
const
464 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.");
561 os <<
"time-window: " << timeWindows;
565 os <<
", time: " << time;
577 os <<
", time-window-complete: ";
598 if (not missing.
empty()) {
600 for (
auto action : missing) {
601 if (not stream.
str().empty()) {
607 "Did you forget to call \"requiresReadingCheckpoint()\" or \"requiresWritingCheckpoint()\"?",
631 convMeasure.measure->newMeasurementSeries();
646 convMeasure.
strict = strict;
647 convMeasure.
measure = std::move(measure);
668 bool allConverged =
true;
669 bool oneSuffices =
false;
670 bool oneStrict =
false;
676 PRECICE_ASSERT(convMeasure.couplingData->previousIteration().size() == convMeasure.couplingData->values().size(), convMeasure.couplingData->previousIteration().size(), convMeasure.couplingData->values().size(), convMeasure.couplingData->getDataName());
677 convMeasure.measure->measure(convMeasure.couplingData->previousIteration(), convMeasure.couplingData->values());
680 _convergenceWriter->writeData(convMeasure.logHeader(), convMeasure.measure->getNormResidual());
683 if (not convMeasure.measure->isConvergence()) {
684 allConverged =
false;
685 if (convMeasure.strict) {
689 "The strict convergence measure for data \"" + convMeasure.couplingData->getDataName() +
690 "\" did not converge within the maximum allowed iterations, which terminates the simulation. "
691 "To avoid this forced termination do not mark the convergence measure as strict.");
693 }
else if (convMeasure.suffices ==
true) {
697 PRECICE_INFO(convMeasure.measure->printState(convMeasure.couplingData->getDataName()));
701 if (not reachedMinIterations) {
702 messageSuffix =
" but hasn't yet reached minimal amount of iterations";
706 }
else if (oneSuffices && not oneStrict) {
707 PRECICE_INFO(
"Sufficient measures converged{}", messageSuffix);
710 return reachedMinIterations && (allConverged || (oneSuffices && not oneStrict));
735 if (convMeasure.doesLogging) {
778 for (
const auto &data :
_allData | boost::adaptors::map_values) {
779 data->storeIteration();
801 for (
const auto &data : dataMap | boost::adaptors::map_values) {
802 if (data->requiresInitialization) {
811 PRECICE_DEBUG(
"measure convergence of the coupling iteration");
831 const auto &stamples = data->stamples();
833 data->sample() = stamples.back().sample;
841 data->setSampleAtTime(
getTime(), data->sample());
874 for (
auto cpldata :
_allData | boost::adaptors::map_values) {
890 for (
auto cpldata :
_allData | boost::adaptors::map_values) {
892 idata.
add(cpldata->getDataID(),
false);
#define PRECICE_ERROR(...)
#define PRECICE_DEBUG(...)
#define PRECICE_TRACE(...)
#define PRECICE_INFO(...)
#define PRECICE_CHECK(check,...)
#define PRECICE_ASSERT(...)
T back_inserter(T... args)
static SerializedStamples empty(Eigen::VectorXd timeStamps, const cplscheme::PtrCouplingData data)
Create SerializedStamples with allocated buffers according to size of CouplingData.
static SerializedStamples serialize(const cplscheme::PtrCouplingData data)
Serializes a given CouplingData into SerializedStamples.
void secondExchange() override final
std::set< Action > _fulfilledActions
void initializeWithZeroInitialData(const DataMap &receiveData)
Initializes storage in receiveData as zero.
std::string printCouplingState() const override
Returns coupling state information.
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 isInitialized() const override final
getter for _isInitialized
ChangedMeshes secondSynchronization() override final
std::string _localParticipant
Local participant name.
double _timeWindowSize
size of time window; _timeWindowSize <= _maxTime
void firstExchange() override final
void determineInitialSend(DataMap &sendData)
Sets _sendsInitializedData, if sendData requires initialization.
virtual void exchangeSecondData()=0
Exchanges the second set of data.
ChangedMeshes firstSynchronization(const ChangedMeshes &changes) override final
void receiveDataForWindowEnd(const m2n::PtrM2N &m2n, const DataMap &receiveData)
Like receiveData, but temporarily sets window time to end of window.
bool requiresSubsteps() const override final
Returns true if any send data of the scheme requires substeps.
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().
void addConvergenceMeasure(int dataID, bool suffices, bool strict, impl::PtrConvergenceMeasure measure, bool doesLogging)
Adds a measure to determine the convergence of coupling iterations.
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 initialize(double startTime, int startTimeWindow) override final
Initializes the coupling scheme.
void storeIteration()
used for storing all Data at end of doImplicitStep for later reference.
bool sendsInitializedData() const override final
Getter for _sendsInitializedData.
void initializeTXTWriters()
Initialize txt writers for iterations and convergence tracking.
bool addComputedTime(double timeToAdd) override final
Adds newly computed time. Has to be called before every advance.
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...
impl::TimeHandler _time
Time handler.
void requireAction(Action action) override final
Sets an action required to be performed by the accessor.
bool _sendsInitializedData
True, if this participant has to send initialized data.
bool _isTimeWindowComplete
True, if _time == _timeWindowStartTime + _timeWindowSize and (coupling has converged or _iterations =...
bool isCouplingOngoing() const override final
Returns true, when the coupled simulation is still ongoing.
int _totalIterations
Number of total iterations performed.
bool anyDataRequiresInitialization(DataMap &dataMap) const
Checks whether any CouplingData in dataMap requires initialization.
double getTime() const override final
getter for _time
Eigen::VectorXd receiveTimes(const m2n::PtrM2N &m2n, int nTimeSteps)
bool hasDataBeenReceived() const override final
getter for _hasDataBeenReceived
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.
double getTimeWindowSize() const override final
Returns the time window size, if one is given by the coupling scheme.
double getTimeWindowStart() const override final
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.
int receiveNumberOfTimeSteps(const m2n::PtrM2N &m2n)
void moveToNextWindow()
finalizes this window's data and initializes data for next window.
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
std::string printBasicState(int timeWindows, double time) const
Prints the coupling state.
double getNextTimeStepMaxSize() const override final
Returns the maximal size of the next time step to be computed.
bool isTimeWindowComplete() const override final
Returns true, when the accessor can advance to the next time window.
std::string printActionsState() const
Prints the action state.
bool hasTimeWindowSize() const override final
Function to check whether time window size is defined by coupling scheme.
bool receivesInitializedData() const
Getter for _receivesInitializedData.
int getTimeWindows() const override final
getter for _timeWindows
ImplicitData implicitDataToReceive() const override
Returns a vector of implicit data to receive in the next advance.
void sendNumberOfTimeSteps(const m2n::PtrM2N &m2n, const int numberOfTimeSteps)
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 advanceTXTWriters()
Advance txt writers for iterations and convergence tracking.
acceleration::PtrAcceleration _acceleration
Acceleration method to speedup iteration convergence.
double getWindowEndTime() const
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 sendTimes(const m2n::PtrM2N &m2n, const Eigen::VectorXd ×)
CouplingMode _couplingMode
Coupling mode used by coupling scheme.
bool willDataBeExchanged(double lastSolverTimeStepSize) const override final
Returns true, if data will be exchanged when calling advance().
bool isActionRequired(Action action) const override final
Returns true, if the given action has to be performed by the accessor.
std::string localParticipant() const override final
Returns the name of the local participant.
void receiveConvergence(const m2n::PtrM2N &m2n)
receives convergence from other participant via m2n
void setNextTimeWindowSize(double timeWindowSize)
Setter for _nextTimeWindowSize.
std::shared_ptr< io::TXTTableWriter > _iterationsWriter
Responsible for monitoring iteration count over time window.
virtual void exchangeInitialData()=0
implements functionality for initialize in base class.
int _iterations
Number of iterations in current time window. _iterations <= _maxIterations.
void markActionFulfilled(Action action) override final
Tells the coupling scheme that the accessor has performed the given action.
virtual void initializeReceiveDataStorage()=0
Functions needed for initialize()
bool isActionFulfilled(Action action) const override final
Returns true, if the given action has to be performed by the accessor.
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.
void finalize() override final
Finalizes the coupling scheme.
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
static const int INFINITE_MAX_ITERATIONS
To be used, when the number of max iterations is infinite (for implicit coupling).
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 std::string toString(Action action)
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.
void resetProgress()
Resets the progress of the time window back to 0.
void resetTo(double timeStart)
Resets the handler to the given time.
bool reachedEndOfWindow(double timeWindowSize) const
double time() const
Returns the current time as a double.
double untilWindowEnd(double timeWindowSize) const
Returns the time distance to the possibly truncated end of the current time window.
void completeTimeWindow(double timeWindowSize)
double windowStart() const
Returns the window start as a double.
void progressBy(double dt)
Progress the time window by the given amount.
static bool isSecondary()
True if this process is running a secondary rank.
contains implementations of coupling schemes for coupled simulations.
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)
bool contained(const ELEMENT_T &element, const std::vector< ELEMENT_T > &vec)
Returns true, if given element is in vector, otherwise false.
T set_difference(T... args)
Holds meta information to perform a convergence measurement.
impl::PtrConvergenceMeasure measure
PtrCouplingData couplingData
void add(DataID did, bool toKeep)