Provide wrapper which connect simulator and writer

This wrapper class aggregate all the result objects (state, timer
etc.) and register itself for notification with the simulator. At
every timestep the simulator should provide a notification. The
wrapper will receive this and pass all the state objects to the
writer(s) which creates a new timestep.

Currently this doesn't work out-of-the-box because only the
two-phase simulator sends notifications and the writer only
understand the state of blackoil simulators, but these two concepts
should be unified.
This commit is contained in:
Roland Kaufmann committed 2013-11-25 14:14:48 +01:00
1 parent ede84e6cc8
commit f710ff71d1
3 files changed
+246

No files matched your search

+2
View File
@@ -99,6 +99,7 @@ list (APPEND MAIN_SOURCE_FILES
opm/core/simulator/BlackoilState.cpp
opm/core/simulator/SimulatorCompressibleTwophase.cpp
opm/core/simulator/SimulatorIncompTwophase.cpp
opm/core/simulator/SimulatorOutput.cpp
opm/core/simulator/SimulatorReport.cpp
opm/core/simulator/SimulatorState.cpp
opm/core/simulator/SimulatorTimer.cpp
@@ -307,6 +308,7 @@ list (APPEND PUBLIC_HEADER_FILES
opm/core/simulator/BlackoilState.hpp
opm/core/simulator/SimulatorCompressibleTwophase.hpp
opm/core/simulator/SimulatorIncompTwophase.hpp
opm/core/simulator/SimulatorOutput.hpp
opm/core/simulator/SimulatorReport.hpp
opm/core/simulator/SimulatorState.hpp
opm/core/simulator/SimulatorTimer.hpp
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright (c) 2013 Uni Research AS
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SimulatorOutput.hpp"
// we need complete definitions for these types
#include <opm/core/io/eclipse/EclipseGridParser.hpp>
#include <opm/core/io/OutputWriter.hpp>
#include <opm/core/simulator/SimulatorTimer.hpp>
using namespace Opm;
SimulatorOutputBase::SimulatorOutputBase (
const parameter::ParameterGroup& params,
std::shared_ptr <EclipseGridParser> parser,
std::shared_ptr <SimulatorTimer> timer,
std::shared_ptr <BlackoilState> state,
std::shared_ptr <WellState> wellState)
// store all parameters passed into the object, making them curried
// parameters to the writeOutput function.
: parser_ (parser )
, timer_ (timer )
, reservoirState_ (state )
, wellState_ (wellState)
// process parameters into a writer. we don't setup a new chain in
// every timestep!
, writer_ (std::move (OutputWriter::create (params, parser_)))
// always start from the first timestep
, next_ (0) {
// make a list of times to dump. since the original list are relative
// timesteps, we make a list of accumulated such to compare with
// current time.
const std::vector <double>& tstep = parser->getTSTEP ().tstep_;
times_.resize (tstep.size (), 0.);
std::partial_sum (tstep.begin(), tstep.end(), times_.begin());
// write the static initialization files, even before simulation starts
writer_->writeInit (*timer);
}
SimulatorOutputBase::operator std::function <void ()> () {
// return (a pointer to) the writeOutput() function as an object
// which can be passed to the event available from the simulator
return std::bind (&SimulatorOutputBase::writeOutput, std::ref (*this));
}
void
SimulatorOutputBase::writeOutput () {
// write output for all timesteps that have passed (usually only
// one, unless you have entered the same time twice, or the simulator
// doesn't honor the TSTEP settings)
for (;
next_ < times_.size () && times_[next_] <= timer_->currentTime ();
++next_) {
// make sure the simulator has spilled all necessary internal
// state. notice that this calls *our* sync, which is overridden
// in the template companion to call the simulator
sync ();
// relay the request to the handlers (setup in the constructor
// from parameters)
writer_->writeTimeStep (*timer_, *reservoirState_, *wellState_);
}
}
void
SimulatorOutputBase::sync () {
// no-op in base class (overridden by simulator-specific template)
}
+154
View File
@@ -0,0 +1,154 @@
/*
Copyright (c) 2013 Uni Research AS
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_SIMULATOR_OUTPUT_HPP
#define OPM_SIMULATOR_OUTPUT_HPP
#include <memory> // unique_ptr, shared_ptr
#include <vector>
namespace Opm {
// forward definitions
class BlackoilState;
class EclipseGridParser;
class OutputWriter;
namespace parameter { class ParameterGroup; }
class SimulatorTimer;
class WellState;
/**
* Encapsulate output writing from simulators. This is essentially
* a function object holding curried arguments to the writing backend
* which is used when invoked through the event handler (which passes
* on no arguments on it own).
*/
class SimulatorOutputBase {
protected:
/**
* Curry arguments for the output writer. These arguments are passed
* to the simulator, but is not passed on to the event handler so it
* need to pick them up from the object members.
*/
SimulatorOutputBase (const parameter::ParameterGroup& p,
std::shared_ptr <EclipseGridParser> parser,
std::shared_ptr <SimulatorTimer> timer,
std::shared_ptr <BlackoilState> state,
std::shared_ptr <WellState> wellState);
/**
* Conversion operator which allows the object to be directly passed
* into an Event and used as a handler.
*
* @see Opm::SimulatorIncompTwophase::timestep_completed
*/
operator std::function <void ()> ();
/// Just hold a reference to these objects that are owned elsewhere.
std::shared_ptr <EclipseGridParser> parser_;
std::shared_ptr <SimulatorTimer> timer_;
std::shared_ptr <BlackoilState> reservoirState_;
std::shared_ptr <WellState> wellState_;
/// Created locally and destructed together with us
std::unique_ptr <OutputWriter> writer_;
/// Call the writers that were created based on the parameters
virtual void writeOutput ();
/// Make sure that the simulator state is up to date before writing
virtual void sync ();
private:
/// Index of the upcoming reporting time
std::vector <double>::size_type next_;
/// Array of times when to write report
std::vector <double> times_;
};
/**
* Create an output writer that is coupled to a simulator capable
* of reading Eclipse deck files. Output will be written only when
* specified in the deck file.
*
* @note
* This class is a template since there is no fixed interface for
* simulators, only an implied type class of common method signatures.
*
* @example
* @code{.cpp}
* // configuration
* ParameterGroup params (argc, argv, false);
*
* // input file
* auto deck = make_shared <EclipseGridParser> ( ... );
*
* // timestep ends up here
* auto timer = make_shared <SimulatorTimer> ();
*
* // state ends up here
* auto state = make_shared <TwophaseState> ();
* auto wellState = make_shared <WellState> ();
*
* // set up simulation
* auto sim = make_shared <SimulatorIncompTwophase> (params, grid, ... );
*
* // use this to dump state to disk
* auto output = make_shared <SimulatorOutput> (
* params, deck, timer, state, wellState, sim);
*
* // start simulation
* sim.run (timer, state, ... )
* @endcode
*
* @todo
* This functionality could be incorporated directly into a simulator
* object.
*/
template <typename Simulator>
struct SimulatorOutput : public SimulatorOutputBase {
SimulatorOutput (const parameter::ParameterGroup& params,
std::shared_ptr <EclipseGridParser> parser,
std::shared_ptr <SimulatorTimer> timer,
std::shared_ptr <BlackoilState> state,
std::shared_ptr <WellState> wellState,
std::shared_ptr <Simulator> sim)
// send all other parameters to base class
: SimulatorOutputBase (params, parser, timer, state, wellState)
// store reference to simulator in derived class
, sim_ (sim) {
// connect simulation with output writer
sim.timestep_completed ().add (*this);
}
protected:
// forward this request to the simulator
virtual void sync () { sim_->sync (); }
private:
/// Reference to the simulator class; needed to ask it to synchronize
std::shared_ptr <Simulator> sim_;
};
}
#endif /* OPM_SIMULATOR_OUTPUT_HPP */