Merge pull request #242 from rolk/242_callback

Let external objects observe individual timesteps in a simulation
This commit is contained in:
Atgeirr Flø Rasmussen 2013-05-22 03:46:02 -07:00
commit 7ee481a601
6 changed files with 69 additions and 6 deletions

View File

@ -29,7 +29,7 @@ set (${project}_DEPS
"CXX11Features"
# various runtime library enhancements
"Boost 1.39.0
COMPONENTS date_time filesystem system unit_test_framework REQUIRED"
COMPONENTS date_time filesystem system unit_test_framework signals REQUIRED"
# matrix library
"BLAS REQUIRED"
"LAPACK REQUIRED"

View File

@ -266,6 +266,7 @@ list (APPEND PUBLIC_HEADER_FILES
opm/core/simulator/BlackoilState.hpp
opm/core/simulator/SimulatorCompressibleTwophase.hpp
opm/core/simulator/SimulatorIncompTwophase.hpp
opm/core/simulator/SimulatorIncompTwophase_impl.hpp
opm/core/simulator/SimulatorReport.hpp
opm/core/simulator/SimulatorTimer.hpp
opm/core/simulator/TwophaseState.hpp

View File

@ -20,7 +20,7 @@ find_opm_package (
"C99;
CXX11Features;
Boost 1.39.0
COMPONENTS date_time filesystem system unit_test_framework REQUIRED;
COMPONENTS date_time filesystem system unit_test_framework signals REQUIRED;
BLAS REQUIRED;
LAPACK REQUIRED;
SuiteSparse COMPONENTS umfpack;

View File

@ -49,6 +49,8 @@
#include <boost/filesystem.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#include <boost/signal.hpp>
#include <numeric>
#include <fstream>
@ -57,9 +59,8 @@
namespace Opm
{
class SimulatorIncompTwophase::Impl
struct SimulatorIncompTwophase::Impl
{
public:
Impl(const parameter::ParameterGroup& param,
const UnstructuredGrid& grid,
const IncompPropertiesInterface& props,
@ -74,7 +75,6 @@ namespace Opm
TwophaseState& state,
WellState& well_state);
private:
// Data.
// Parameters for output.
bool output_;
@ -101,6 +101,9 @@ namespace Opm
boost::scoped_ptr<TransportSolverTwophaseInterface> tsolver_;
// Misc. data
std::vector<int> allcells_;
// list of hooks that are notified when a timestep completes
boost::signal0 <void> timestep_completed;
};
@ -130,6 +133,11 @@ namespace Opm
return pimpl_->run(timer, state, well_state);
}
// connect the hook to the signal in the implementation class
void SimulatorIncompTwophase::connect_timestep_impl (boost::function0 <void> hook) {
pimpl_->timestep_completed.connect (hook);
}
static void reportVolumes(std::ostream &os, double satvol[2], double tot_porevol_init,
double tot_injected[2], double tot_produced[2],
double injected[2], double produced[2],
@ -411,6 +419,8 @@ namespace Opm
double ptime = 0.0;
Opm::time::StopWatch transport_timer;
double ttime = 0.0;
Opm::time::StopWatch callback_timer;
double time_in_callbacks = 0.0;
Opm::time::StopWatch step_timer;
Opm::time::StopWatch total_timer;
total_timer.start();
@ -587,6 +597,12 @@ namespace Opm
if (output_) {
sreport.reportParam(tstep_os);
}
// notify all clients that we are done with the timestep
callback_timer.start ();
timestep_completed ();
callback_timer.stop ();
time_in_callbacks += callback_timer.secsSinceStart ();
}
if (output_) {
@ -612,7 +628,7 @@ namespace Opm
SimulatorReport report;
report.pressure_time = ptime;
report.transport_time = ttime;
report.total_time = total_timer.secsSinceStart();
report.total_time = total_timer.secsSinceStart() - time_in_callbacks;
return report;
}

View File

@ -21,6 +21,8 @@
#define OPM_SIMULATORINCOMPTWOPHASE_HEADER_INCLUDED
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <functional> // bind
#include <vector>
struct UnstructuredGrid;
@ -88,12 +90,44 @@ namespace Opm
TwophaseState& state,
WellState& well_state);
/// Register a callback for notifications about completed timestep.
/// The specified method of the object is called when the simulator
/// has completed a timestep and the state objects are (possibly)
/// changed.
/// If you want to know the current timestep, the callback must
/// also monitor the timer object which was passed to run().
/// \tparam T Type of the callback object.
/// \tparam callback Address of a member function of T which will
/// be invoked when a timestep completes.
/// \param[in] t Object which will receive notifications. The
/// lifetime of the object must span over the
/// duration of the simulation, and it is your
/// responsibility to ensure that.
/// \example
/// \code{.cpp}
/// struct Foo {
/// void bar () { cout << "Called!" << endl; }
/// };
///
/// SimulatorIncompTwophase sim (...);
/// Foo f;
/// sim.connect_timestep <Foo, &Foo::bar> (f);
/// sim.run (...);
/// \endcode
template <typename T, void (T::*callback)()>
void connect_timestep (T& t);
private:
class Impl;
// Using shared_ptr instead of scoped_ptr since scoped_ptr requires complete type for Impl.
boost::shared_ptr<Impl> pimpl_;
// implementation which is not templated, and can be in library
void connect_timestep_impl (boost::function0<void> hook);
};
} // namespace Opm
#include "SimulatorIncompTwophase_impl.hpp"
#endif // OPM_SIMULATORINCOMPTWOPHASE_HEADER_INCLUDED

View File

@ -0,0 +1,12 @@
#ifndef OPM_SIMULATORINCOMPTWOPHASE_HEADER_INCLUDED
#error Do not include SimulatorIncompTwophase directly!
#endif
namespace Opm {
template <typename T, void (T::*callback)()>
inline void SimulatorIncompTwophase::connect_timestep (T& t) {
connect_timestep_impl (boost::function0<void> (std::bind (callback, t)));
}
} /* namespace Opm */