Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# DuMuX-preCICE change log

## latest

- Added dumux-customised checkpointing feature [#58](https://github.com/precice/dumux-adapter/pull/58)
- Improved ID lookup from `log(n)` to constant where n is the mesh size [#44](https://github.com/precice/dumux-adapter/pull/44)
- Update DUNE version in the CI to 2.10 and update examples for compatibility [#45](https://github.com/precice/dumux-adapter/pull/45)

Expand Down
2 changes: 1 addition & 1 deletion dumux-precice/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ install(FILES
couplingadapter.hh
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux-precice)

dune_library_add_sources(dumux-precice SOURCES couplingadapter.cc dumuxpreciceindexmapper.cc)
dune_library_add_sources(dumux-precice SOURCES couplingadapter.cc dumuxpreciceindexmapper.cc solverstate.cc)
target_link_libraries(dumux-precice PRIVATE precice::precice)
21 changes: 17 additions & 4 deletions dumux-precice/couplingadapter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,28 @@ bool CouplingAdapter::requiresToWriteInitialData()
return precice_->requiresInitialData();
}

bool CouplingAdapter::requiresToReadCheckpoint()
bool CouplingAdapter::writeCheckpointIfRequired()
{
assert(wasCreated_);
return precice_->requiresReadingCheckpoint();
if (!precice_->requiresWritingCheckpoint()) {
return false;
}
for (auto &state : states_) {
state->writeState();
}
return true;
}

bool CouplingAdapter::requiresToWriteCheckpoint()
bool CouplingAdapter::readCheckpointIfRequired()
{
assert(wasCreated_);
return precice_->requiresWritingCheckpoint();
if (!precice_->requiresReadingCheckpoint()) {
return false;
}
for (auto &state : states_) {
state->readState();
}
return true;
}

CouplingAdapter::~CouplingAdapter() {}
60 changes: 52 additions & 8 deletions dumux-precice/couplingadapter.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <string>

#include "dumuxpreciceindexmapper.hh"
#include "solverstate.hh"

/*!
* @brief Namespace of dumux-precice
Expand Down Expand Up @@ -54,6 +55,11 @@ private:
*
*/
Internal::DumuxPreciceIndexMapper<FaceID, precice::VertexID> indexMapper_;
/*!
* @brief Store the states of the solver for checkpointing.
*
*/
std::vector<std::unique_ptr<SolverStateBase>> states_;
/*!
* @brief Get the number of quantities exchanged.
*
Expand Down Expand Up @@ -111,21 +117,35 @@ public:
* @return double time step size
*/
double getMaxTimeStepSize() const;

/*!
* @brief Checks if the participant is required to read an iteration checkpoint. If true, the participant is required to read an iteration checkpoint before calling advance().
* @brief Initializes the checkpointing functionality.
*
* @return true Simulation checkpoint has to be restored.
* @return false No further action is needed.
* This function needs to be called at least once before using the checkpointing functionality.
*
* @param[in] x Solution vector
* @param[in] gv Grid variables
* @param[in] tl Time loop
*/
bool requiresToReadCheckpoint();
template<class SolutionVector, class GridVariables, class TimeLoop>
void initializeCheckpoint(SolutionVector &x,
GridVariables &gv,
TimeLoop &tl);

template<class SolutionVector, class GridVariables>
void initializeCheckpoint(SolutionVector &x, GridVariables &gv);

template<class SolutionVector>
void initializeCheckpoint(SolutionVector &x);
/*!
* @brief Checks if the participant is required to write an iteration checkpoint. If true, the participant is required to write an iteration checkpoint before calling advance().
* @brief Writes the solver state to a checkpoint if required by preCICE.
*
* @return true Simulation checkpoints needs to be stored.
* @return false No further action is needed.
*/
bool requiresToWriteCheckpoint();
bool writeCheckpointIfRequired();
/*!
* @brief Reads the solver state from a checkpoint if required by preCICE.
*/
bool readCheckpointIfRequired();

/*!
* @brief Checks if the participant is required to provide initial data. If true, the participant needs to write initial data to defined vertices prior to calling initialize().
Expand Down Expand Up @@ -280,5 +300,29 @@ public:
void print(std::ostream &os);
};

template<class SolutionVector, class GridVariables, class TimeLoop>
void CouplingAdapter::initializeCheckpoint(SolutionVector &x,
GridVariables &gv,
TimeLoop &tl)
{
states_.emplace_back(
std::make_unique<SolverStateGridVarTimeLoop<SolutionVector,
GridVariables, TimeLoop>>(
x, gv, tl));
}

template<class SolutionVector, class GridVariables>
void CouplingAdapter::initializeCheckpoint(SolutionVector &x, GridVariables &gv)
{
states_.emplace_back(
std::make_unique<SolverStateGridVar<SolutionVector, GridVariables>>(
x, gv));
}

template<class SolutionVector>
void CouplingAdapter::initializeCheckpoint(SolutionVector &x)
{
states_.emplace_back(std::make_unique<SolverStateOnly<SolutionVector>>(x));
}
} // namespace Dumux::Precice
#endif
1 change: 1 addition & 0 deletions dumux-precice/solverstate.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "solverstate.hh"
99 changes: 99 additions & 0 deletions dumux-precice/solverstate.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#ifndef SOLVERSTATE_HH
#define SOLVERSTATE_HH

#include <precice/precice.hpp>

/*!
* @brief Namespace of dumux-precice
*
*/
namespace Dumux::Precice
{
struct SolverStateBase {
virtual ~SolverStateBase() = default;
virtual void writeState() = 0;
virtual void readState() = 0;
};
/*!
* @brief A class to store and provide the state of the solver while checkpointing, one SolutionVector object is supported.
*/
template<class SolutionVector>
class SolverStateOnly : public SolverStateBase
{
private:
SolutionVector *x_;
SolutionVector xCheckpoint_;

public:
SolverStateOnly(SolutionVector &x) : x_(&x), xCheckpoint_(*x_) {}

void writeState() override { xCheckpoint_ = *x_; }

void readState() override { *x_ = xCheckpoint_; }
};
/*!
* @brief A class to store and provide the state of the solver while checkpointing, one SolutionVector object is supported.
*/
template<class SolutionVector, class GridVariables>
class SolverStateGridVar : public SolverStateBase
{
private:
SolutionVector *x_;
SolutionVector xCheckpoint_;
GridVariables *gv_;

public:
SolverStateGridVar(SolutionVector &x, GridVariables &gv)
: x_(&x), xCheckpoint_(*x_), gv_(&gv)
{
}

void writeState() override { xCheckpoint_ = *x_; }

void readState() override
{
*x_ = xCheckpoint_;
gv_->update(*x_);
}
};
/*!
* @brief A class to store and provide the state of the solver while checkpointing, one SolutionVector object is supported.
*/
template<class SolutionVector, class GridVariables, class TimeLoop>
class SolverStateGridVarTimeLoop : public SolverStateBase
{
private:
SolutionVector *x_;
SolutionVector xCheckpoint_;
GridVariables *gv_;
TimeLoop *tl_;
double timeCheckpoint_ = 0.0;
double dtCheckpoint_ = 0.0;
long timeStepCheckpoint_ = 0;

public:
SolverStateGridVarTimeLoop(SolutionVector &x,
GridVariables &gv,
TimeLoop &tl)
: x_(&x), xCheckpoint_(*x_), gv_(&gv), tl_(&tl)
{
}

void writeState() override
{
xCheckpoint_ = *x_;
timeCheckpoint_ = tl_->time();
timeStepCheckpoint_ = tl_->timeStepIndex();
dtCheckpoint_ = tl_->timeStepSize();
}

void readState() override
{
*x_ = xCheckpoint_;
gv_->update(*x_);
tl_->setTime(timeCheckpoint_, timeStepCheckpoint_);
tl_->setTimeStepSize(dtCheckpoint_);
}
};
} // namespace Dumux::Precice
#endif
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
add_subdirectory(ff-pm)
add_subdirectory(dummysolver)
add_subdirectory(singleCheckpointTest)
4 changes: 2 additions & 2 deletions examples/dummysolver/main_dummysolver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ try {
int iter = 0;

while (couplingParticipant.isCouplingOngoing()) {
if (couplingParticipant.requiresToWriteCheckpoint()) {
if (couplingParticipant.writeCheckpointIfRequired()) {
std::cout << "DUMMY (" << mpiHelper.rank()
<< "): Writing iteration checkpoint\n";
}
Expand Down Expand Up @@ -244,7 +244,7 @@ try {
preciceDt = couplingParticipant.getMaxTimeStepSize();
couplingParticipant.advance(preciceDt);

if (couplingParticipant.requiresToReadCheckpoint()) {
if (couplingParticipant.readCheckpointIfRequired()) {
std::cout << "DUMMY (" << mpiHelper.rank()
<< "): Reading iteration checkpoint\n";
} else {
Expand Down
23 changes: 5 additions & 18 deletions examples/ff-pm/main_ff.cc
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,9 @@ try {
couplingParticipant.writeQuantityToOtherSolver(meshName, dataNameP);
}
couplingParticipant.initialize();
couplingParticipant.initializeCheckpoint(sol[momentumIdx],
*momentumGridVariables);
couplingParticipant.initializeCheckpoint(sol[massIdx], *massGridVariables);

// the assembler for a stationary problem
using Assembler =
Expand All @@ -468,16 +471,11 @@ try {

double preciceDt = couplingParticipant.getMaxTimeStepSize();
auto dt = preciceDt;
auto sol_checkpoint = sol;

double vtkTime = 1.0;
size_t iter = 0;

while (couplingParticipant.isCouplingOngoing()) {
if (couplingParticipant.requiresToWriteCheckpoint()) {
//DO CHECKPOINTING
sol_checkpoint = sol;
}
couplingParticipant.writeCheckpointIfRequired();

couplingParticipant.readQuantityFromOtherSolver(meshName, dataNameV,
dt);
Expand All @@ -495,24 +493,13 @@ try {
momentumProblem, *momentumGridVariables, sol[momentumIdx], meshName,
dataNameP);
couplingParticipant.writeQuantityToOtherSolver(meshName, dataNameP);
//Read checkpoint
freeFlowVtkWriter.write(vtkTime);
vtkTime += 1.;
couplingParticipant.advance(dt);
preciceDt = couplingParticipant.getMaxTimeStepSize();
dt = std::min(preciceDt, dt);

++iter;

if (couplingParticipant.requiresToReadCheckpoint()) {
sol = sol_checkpoint;
momentumGridVariables->update(sol[momentumIdx]);
massGridVariables->update(sol[massIdx]);
momentumGridVariables->advanceTimeStep();
massGridVariables->advanceTimeStep();
} else // coupling successful
{
// write vtk output
if (!couplingParticipant.readCheckpointIfRequired()) {
freeFlowVtkWriter.write(vtkTime);
}
}
Expand Down
28 changes: 9 additions & 19 deletions examples/ff-pm/main_pm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,9 @@ try {
auto darcyProblem = std::make_shared<DarcyProblem>(darcyGridGeometry);

// the solution vector
GetPropType<DarcyTypeTag, Properties::SolutionVector> sol;
using SolutionVector =
GetPropType<DarcyTypeTag, Properties::SolutionVector>;
SolutionVector sol;
sol.resize(darcyGridGeometry->numDofs());

// Initialize preCICE.Tell preCICE about:
Expand Down Expand Up @@ -436,6 +438,9 @@ try {
}
couplingParticipant.initialize();

//initialize checkpointing
couplingParticipant.initializeCheckpoint(sol, *darcyGridVariables);

// the assembler for a stationary problem
using Assembler = FVAssembler<DarcyTypeTag, DiffMethod::numeric>;
auto assembler = std::make_shared<Assembler>(
Expand All @@ -453,16 +458,11 @@ try {

double preciceDt = couplingParticipant.getMaxTimeStepSize();
auto dt = preciceDt;
auto sol_checkpoint = sol;

double vtkTime = 1.0;
size_t iter = 0;

while (couplingParticipant.isCouplingOngoing()) {
if (couplingParticipant.requiresToWriteCheckpoint()) {
//DO CHECKPOINTING
sol_checkpoint = sol;
}
couplingParticipant.writeCheckpointIfRequired();

couplingParticipant.readQuantityFromOtherSolver(meshName, dataNameP,
dt);
Expand All @@ -485,19 +485,9 @@ try {
preciceDt = couplingParticipant.getMaxTimeStepSize();
dt = std::min(preciceDt, dt);

++iter;

if (couplingParticipant.requiresToReadCheckpoint()) {
//Read checkpoint
darcyVtkWriter.write(vtkTime);
darcyVtkWriter.write(vtkTime);
if (couplingParticipant.readCheckpointIfRequired()) {
vtkTime += 1.;
sol = sol_checkpoint;
darcyGridVariables->update(sol);
darcyGridVariables->advanceTimeStep();
} else // coupling successful
{
// write vtk output
darcyVtkWriter.write(vtkTime);
}
}
// write vtk output
Expand Down
Loading