mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Added a parallel aware logger for switching wells.
It will collect all the switches. Afterwards they are collect on the root process and logged there. This commit includes a small test program.
This commit is contained in:
@@ -66,6 +66,7 @@ list (APPEND MAIN_SOURCE_FILES
|
||||
opm/polymer/fullyimplicit/PolymerPropsAd.cpp
|
||||
opm/simulators/SimulatorCompressibleTwophase.cpp
|
||||
opm/simulators/SimulatorIncompTwophase.cpp
|
||||
opm/simulators/WellSwitchingLogger.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -87,6 +88,7 @@ list (APPEND TEST_SOURCE_FILES
|
||||
tests/test_solventprops_ad.cpp
|
||||
tests/test_multisegmentwells.cpp
|
||||
# tests/test_thresholdpressure.cpp
|
||||
tests/test_wellswitchlogger.cpp
|
||||
)
|
||||
|
||||
list (APPEND TEST_DATA_FILES
|
||||
@@ -240,5 +242,6 @@ list (APPEND PUBLIC_HEADER_FILES
|
||||
opm/polymer/fullyimplicit/WellStateFullyImplicitBlackoilPolymer.hpp
|
||||
opm/simulators/SimulatorCompressibleTwophase.hpp
|
||||
opm/simulators/SimulatorIncompTwophase.hpp
|
||||
opm/simulators/WellSwitchingLogger.hpp
|
||||
)
|
||||
|
||||
|
||||
@@ -150,12 +150,19 @@ namespace Opm
|
||||
asImpl().setupOutputWriter();
|
||||
asImpl().setupLinearSolver();
|
||||
asImpl().createSimulator();
|
||||
|
||||
|
||||
// Run.
|
||||
return asImpl().runSimulator();
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
std::cerr << "Program threw an exception: " << e.what() << "\n";
|
||||
std::ostringstream message;
|
||||
message << "Program threw an exception: " << e.what();
|
||||
|
||||
if( output_cout_ )
|
||||
{
|
||||
OpmLog::error(message.str());
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -389,7 +396,6 @@ namespace Opm
|
||||
logFileStream << baseName << ".PRT";
|
||||
debugFileStream << "." << baseName << ".DEBUG";
|
||||
}
|
||||
if ( must_distribute_ && mpi_rank_ != 0 )
|
||||
{
|
||||
// Added rank to log file for non-zero ranks.
|
||||
// This prevents message loss.
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace Opm {
|
||||
MultisegmentWells::
|
||||
MultisegmentWells(const Wells* wells_arg,
|
||||
const std::vector< const Well* >& wells_ecl,
|
||||
const int time_step)
|
||||
const int time_step, const Communication& comm)
|
||||
: wells_multisegment_( createMSWellVector(wells_arg, wells_ecl, time_step) )
|
||||
, wops_ms_(wells_multisegment_)
|
||||
, num_phases_(wells_arg ? wells_arg->number_of_phases : 0)
|
||||
@@ -158,6 +158,7 @@ namespace Opm {
|
||||
, segment_comp_surf_volume_current_(num_phases_, ADB::null())
|
||||
, segment_mass_flow_rates_(ADB::null())
|
||||
, segment_viscosities_(ADB::null())
|
||||
, comm_(comm)
|
||||
{
|
||||
const int nw = wells_multisegment_.size();
|
||||
int nperf_total = 0;
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#ifndef OPM_MULTISEGMENTWELLS_HEADER_INCLUDED
|
||||
#define OPM_MULTISEGMENTWELLS_HEADER_INCLUDED
|
||||
|
||||
#include <dune/common/parallel/mpihelper.hh>
|
||||
|
||||
#include <opm/common/utility/platform_dependent/disable_warnings.h>
|
||||
#include <Eigen/Eigen>
|
||||
#include <Eigen/Sparse>
|
||||
@@ -41,6 +43,7 @@
|
||||
|
||||
#include <opm/autodiff/WellMultiSegment.hpp>
|
||||
#include <opm/autodiff/WellDensitySegmented.hpp>
|
||||
#include <opm/simulators/WellSwitchingLogger.hpp>
|
||||
|
||||
|
||||
|
||||
@@ -78,13 +81,17 @@ namespace Opm {
|
||||
Eigen::Dynamic,
|
||||
Eigen::Dynamic,
|
||||
Eigen::RowMajor>;
|
||||
using Communication =
|
||||
Dune::CollectiveCommunication<typename Dune::MPIHelper
|
||||
::MPICommunicator>;
|
||||
|
||||
// --------- Public methods ---------
|
||||
// TODO: using a vector of WellMultiSegmentConstPtr for now
|
||||
// TODO: it should use const Wells or something else later.
|
||||
MultisegmentWells(const Wells* wells_arg,
|
||||
const std::vector< const Well* >& wells_ecl,
|
||||
const int time_step);
|
||||
const int time_step,
|
||||
const Communication& comm=Communication());
|
||||
|
||||
std::vector<WellMultiSegmentConstPtr> createMSWellVector(const Wells* wells_arg,
|
||||
const std::vector< const Well* >& wells_ecl,
|
||||
@@ -305,6 +312,7 @@ namespace Opm {
|
||||
Vector well_perforation_densities_;
|
||||
Vector well_perforation_pressure_diffs_;
|
||||
|
||||
Communication comm_;
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
@@ -824,6 +824,8 @@ namespace Opm
|
||||
MultisegmentWells::
|
||||
updateWellControls(WellState& xw) const
|
||||
{
|
||||
wellhelpers::WellSwitchingLogger logger(comm_);
|
||||
|
||||
if( msWells().empty() ) return ;
|
||||
|
||||
std::string modestring[4] = { "BHP", "THP", "RESERVOIR_RATE", "SURFACE_RATE" };
|
||||
@@ -860,9 +862,9 @@ namespace Opm
|
||||
if (ctrl_index != nwc) {
|
||||
// Constraint number ctrl_index was broken, switch to it.
|
||||
// Each well is only active on one process. Therefore we always print the sitch info.
|
||||
std::cout << "Switching control mode for well " << msWells()[w]->name()
|
||||
<< " from " << modestring[well_controls_iget_type(wc, current)]
|
||||
<< " to " << modestring[well_controls_iget_type(wc, ctrl_index)] << std::endl;
|
||||
logger.wellSwitched(msWells()[w]->name(),
|
||||
well_controls_iget_type(wc, current),
|
||||
well_controls_iget_type(wc, ctrl_index));
|
||||
xw.currentControls()[w] = ctrl_index;
|
||||
current = xw.currentControls()[w];
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#ifndef OPM_STANDARDWELLS_HEADER_INCLUDED
|
||||
#define OPM_STANDARDWELLS_HEADER_INCLUDED
|
||||
|
||||
#include <dune/common/parallel/mpihelper.hh>
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
|
||||
#include <opm/common/utility/platform_dependent/disable_warnings.h>
|
||||
@@ -39,7 +41,7 @@
|
||||
#include <opm/autodiff/AutoDiffBlock.hpp>
|
||||
#include <opm/autodiff/AutoDiffHelpers.hpp>
|
||||
#include <opm/autodiff/BlackoilPropsAdInterface.hpp>
|
||||
|
||||
#include <opm/simulators/WellSwitchingLogger.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
@@ -57,6 +59,9 @@ namespace Opm {
|
||||
// --------- Types ---------
|
||||
using ADB = AutoDiffBlock<double>;
|
||||
using Vector = ADB::V;
|
||||
using Communication =
|
||||
Dune::CollectiveCommunication<typename Dune::MPIHelper
|
||||
::MPICommunicator>;
|
||||
|
||||
// copied from BlackoilModelBase
|
||||
// should put to somewhere better
|
||||
@@ -65,7 +70,8 @@ namespace Opm {
|
||||
Eigen::Dynamic,
|
||||
Eigen::RowMajor>;
|
||||
// --------- Public methods ---------
|
||||
explicit StandardWells(const Wells* wells_arg);
|
||||
explicit StandardWells(const Wells* wells_arg,
|
||||
const Communication& comm=Communication());
|
||||
|
||||
void init(const BlackoilPropsAdInterface* fluid_arg,
|
||||
const std::vector<bool>* active_arg,
|
||||
@@ -205,6 +211,8 @@ namespace Opm {
|
||||
bool store_well_perforation_fluxes_;
|
||||
Vector well_perforation_fluxes_;
|
||||
|
||||
Communication comm_;
|
||||
|
||||
// protected methods
|
||||
template <class SolutionState, class WellState>
|
||||
void computePropertiesForWellConnectionPressures(const SolutionState& state,
|
||||
|
||||
@@ -71,7 +71,8 @@ namespace Opm
|
||||
|
||||
|
||||
|
||||
StandardWells::StandardWells(const Wells* wells_arg)
|
||||
StandardWells::StandardWells(const Wells* wells_arg,
|
||||
const Communication& comm)
|
||||
: wells_active_(wells_arg!=nullptr)
|
||||
, wells_(wells_arg)
|
||||
, wops_(wells_arg)
|
||||
@@ -82,6 +83,7 @@ namespace Opm
|
||||
, well_perforation_densities_(Vector())
|
||||
, well_perforation_pressure_diffs_(Vector())
|
||||
, store_well_perforation_fluxes_(false)
|
||||
, comm_(comm)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -706,9 +708,10 @@ namespace Opm
|
||||
StandardWells::
|
||||
updateWellControls(WellState& xw) const
|
||||
{
|
||||
wellhelpers::WellSwitchingLogger logger(comm_);
|
||||
|
||||
if( !localWellsActive() ) return ;
|
||||
|
||||
std::string modestring[4] = { "BHP", "THP", "RESERVOIR_RATE", "SURFACE_RATE" };
|
||||
// Find, for each well, if any constraints are broken. If so,
|
||||
// switch control to first broken constraint.
|
||||
const int np = wells().number_of_phases;
|
||||
@@ -743,11 +746,9 @@ namespace Opm
|
||||
// Constraint number ctrl_index was broken, switch to it.
|
||||
// We disregard terminal_ouput here as with it only messages
|
||||
// for wells on one process will be printed.
|
||||
std::ostringstream ss;
|
||||
ss << "Switching control mode for well " << wells().name[w]
|
||||
<< " from " << modestring[well_controls_iget_type(wc, current)]
|
||||
<< " to " << modestring[well_controls_iget_type(wc, ctrl_index)] << std::endl;
|
||||
OpmLog::info(ss.str());
|
||||
logger.wellSwitched(wells().name[w],
|
||||
well_controls_iget_type(wc, current),
|
||||
well_controls_iget_type(wc, ctrl_index));
|
||||
xw.currentControls()[w] = ctrl_index;
|
||||
current = xw.currentControls()[w];
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ namespace Opm {
|
||||
|
||||
namespace wellhelpers
|
||||
{
|
||||
|
||||
|
||||
inline
|
||||
double rateToCompare(const std::vector<double>& well_phase_flow_rate,
|
||||
const int well,
|
||||
|
||||
206
opm/simulators/WellSwitchingLogger.cpp
Normal file
206
opm/simulators/WellSwitchingLogger.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
Copyright 2016 Dr. Blatt - HPC-Simulation-Software & Services
|
||||
Copyright 2016 Statoil 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/>.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include <opm/simulators/WellSwitchingLogger.hpp>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
namespace wellhelpers
|
||||
{
|
||||
|
||||
#if HAVE_MPI
|
||||
int WellSwitchingLogger::calculateMessageSize(std::vector<int>& well_name_length)
|
||||
{
|
||||
|
||||
// Each process will send a message to the root process with
|
||||
// the following data:
|
||||
// total number of switches, for each switch the length of the
|
||||
// well name, for each switch the well name and the two controls.
|
||||
well_name_length.reserve(switchMap_.size());
|
||||
|
||||
for(const auto& switchEntry : switchMap_)
|
||||
{
|
||||
int length = switchEntry.first.size() +1; //we write an additional \0
|
||||
well_name_length.push_back(length);
|
||||
}
|
||||
|
||||
// compute the message size
|
||||
int message_size = 0;
|
||||
int increment = 0;
|
||||
// number of switches
|
||||
MPI_Pack_size(1, MPI_INT, MPI_COMM_WORLD, &message_size);
|
||||
message_size += increment;
|
||||
// const char* length include delimiter for each switch
|
||||
MPI_Pack_size(switchMap_.size(), MPI_INT, MPI_COMM_WORLD, &increment);
|
||||
message_size += increment;
|
||||
// for each well the name + two controls in one write
|
||||
auto length = well_name_length.begin();
|
||||
|
||||
for(const auto& switchEntry : switchMap_)
|
||||
{
|
||||
// well name
|
||||
MPI_Pack_size(*length, MPI_CHAR, MPI_COMM_WORLD, &increment);
|
||||
message_size += increment;
|
||||
// controls
|
||||
MPI_Pack_size(2, MPI_CHAR, MPI_COMM_WORLD, &increment);
|
||||
message_size += increment;
|
||||
++length;
|
||||
}
|
||||
return message_size;
|
||||
}
|
||||
|
||||
void WellSwitchingLogger::packData(std::vector<int>& well_name_length,
|
||||
std::vector<char>& buffer)
|
||||
{
|
||||
// Pack the data
|
||||
// number of switches
|
||||
int offset = 0;
|
||||
int no_switches = switchMap_.size();
|
||||
MPI_Pack(&no_switches, 1, MPI_INT, buffer.data(), buffer.size(),
|
||||
&offset, MPI_COMM_WORLD);
|
||||
MPI_Pack(well_name_length.data(), well_name_length.size(),
|
||||
MPI_INT, buffer.data(), buffer.size(),
|
||||
&offset, MPI_COMM_WORLD);
|
||||
|
||||
for(const auto& switchEntry : switchMap_)
|
||||
{
|
||||
// well name
|
||||
auto& well_name = switchEntry.first;
|
||||
MPI_Pack(const_cast<char*>(well_name.c_str()), well_name.size()+1,
|
||||
MPI_CHAR, buffer.data(), buffer.size(),
|
||||
&offset, MPI_COMM_WORLD);
|
||||
|
||||
// controls
|
||||
MPI_Pack(const_cast<char*>(switchEntry.second.data()), 2 , MPI_CHAR,
|
||||
buffer.data(), buffer.size(), &offset, MPI_COMM_WORLD);
|
||||
}
|
||||
}
|
||||
|
||||
void WellSwitchingLogger::unpackDataAndLog(std::vector<char>& recv_buffer,
|
||||
const std::vector<int>& displ)
|
||||
{
|
||||
for(int p=1; p < cc_.size(); ++p)
|
||||
{
|
||||
int offset = displ[p];
|
||||
int no_switches = 0;
|
||||
MPI_Unpack(recv_buffer.data(), recv_buffer.size(), &offset,
|
||||
&no_switches, 1, MPI_INT, MPI_COMM_WORLD);
|
||||
|
||||
if ( no_switches == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<int> well_name_length(no_switches);
|
||||
|
||||
MPI_Unpack(recv_buffer.data(), recv_buffer.size(), &offset,
|
||||
well_name_length.data(), well_name_length.size(),
|
||||
MPI_INT, MPI_COMM_WORLD);
|
||||
|
||||
for ( int i = 0; i < no_switches; ++i )
|
||||
{
|
||||
char well_name[well_name_length[i]] = {};
|
||||
MPI_Unpack(recv_buffer.data(), recv_buffer.size(), &offset,
|
||||
well_name, well_name_length[i], MPI_CHAR,
|
||||
MPI_COMM_WORLD);
|
||||
|
||||
std::array<char,2> fromto{{}};
|
||||
MPI_Unpack(recv_buffer.data(), recv_buffer.size(), &offset,
|
||||
fromto.data(), 2, MPI_CHAR, MPI_COMM_WORLD);
|
||||
|
||||
logSwitch(well_name, fromto, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WellSwitchingLogger::logSwitch(const char* name, std::array<char,2> fromto,
|
||||
int rank)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "Switching control mode for well " << name
|
||||
<< " from " << modestring[WellControlType(fromto[0])]
|
||||
<< " to " << modestring[WellControlType(fromto[1])]
|
||||
<< " on rank " << rank << std::endl;
|
||||
OpmLog::info(ss.str());
|
||||
}
|
||||
#endif
|
||||
|
||||
void WellSwitchingLogger::gatherDataAndLog()
|
||||
{
|
||||
|
||||
#if HAVE_MPI
|
||||
if(cc_.size() == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> message_sizes;
|
||||
std::vector<int> well_name_length;
|
||||
int message_size = calculateMessageSize(well_name_length);
|
||||
|
||||
if ( cc_.rank() == 0 ){
|
||||
for(const auto& entry : switchMap_)
|
||||
{
|
||||
logSwitch(entry.first.c_str(), entry.second,0);
|
||||
}
|
||||
|
||||
message_sizes.resize(cc_.size());
|
||||
}
|
||||
|
||||
MPI_Gather(&message_size, 1, MPI_INT, message_sizes.data(),
|
||||
1, MPI_INT, 0, MPI_COMM_WORLD);
|
||||
|
||||
std::vector<char> buffer(message_size);
|
||||
packData(well_name_length, buffer);
|
||||
|
||||
std::vector<int> displ;
|
||||
|
||||
if ( cc_.rank() == 0){
|
||||
// last entry will be total size of
|
||||
displ.resize(cc_.size() + 1, 0);
|
||||
std::partial_sum(message_sizes.begin(), message_sizes.end(),
|
||||
displ.begin()+1);
|
||||
}
|
||||
std::vector<char> recv_buffer;
|
||||
if ( cc_.rank() == 0 ){
|
||||
recv_buffer.resize(displ[cc_.size()]);
|
||||
}
|
||||
|
||||
MPI_Gatherv(buffer.data(), buffer.size(), MPI_PACKED,
|
||||
recv_buffer.data(), message_sizes.data(),
|
||||
displ.data(), MPI_PACKED, 0, MPI_COMM_WORLD);
|
||||
if ( cc_.rank() == 0 )
|
||||
{
|
||||
unpackDataAndLog(recv_buffer, displ);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
WellSwitchingLogger::~WellSwitchingLogger()
|
||||
{
|
||||
gatherDataAndLog();
|
||||
}
|
||||
} // end namespace wellhelpers
|
||||
} // end namespace Opm
|
||||
112
opm/simulators/WellSwitchingLogger.hpp
Normal file
112
opm/simulators/WellSwitchingLogger.hpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
Copyright 2016 Dr. Blatt - HPC-Simulation-Software & Services
|
||||
Copyright 2016 Statoil 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_WELLSWITCHINGLOGGER_HEADER_INCLUDED
|
||||
#define OPM_WELLSWITCHINGLOGGER_HEADER_INCLUDED
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <dune/common/parallel/mpihelper.hh>
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
|
||||
#include <opm/core/well_controls.h>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
namespace wellhelpers
|
||||
{
|
||||
|
||||
/// \brief Utility class to handle the log messages about well switching.
|
||||
///
|
||||
/// In parallel all the messages will be send to a root processor
|
||||
/// and logged there.
|
||||
class WellSwitchingLogger
|
||||
{
|
||||
typedef std::map<std::string, std::array<char,2> > SwitchMap;
|
||||
|
||||
public:
|
||||
/// \brief The type of the collective communication used.
|
||||
typedef Dune::CollectiveCommunication<typename Dune::MPIHelper::MPICommunicator>
|
||||
Communication;
|
||||
|
||||
/// \brief Constructor.
|
||||
///
|
||||
/// \param cc The collective communication to use.
|
||||
explicit WellSwitchingLogger(const Communication& cc=Communication())
|
||||
: cc_(cc)
|
||||
{}
|
||||
|
||||
/// \brief Log that a well switched.
|
||||
/// \param name The name of the well.
|
||||
/// \param from The control of the well before the switch.
|
||||
/// \param to The control of the well after the switch.
|
||||
void wellSwitched(std::string name,
|
||||
WellControlType from,
|
||||
WellControlType to)
|
||||
{
|
||||
if( cc_.size() > 1 )
|
||||
{
|
||||
using Pair = typename SwitchMap::value_type;
|
||||
switchMap_.insert(Pair(name, {char(from), char(to)}));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "Switching control mode for well " << name
|
||||
<< " from " << modestring[from]
|
||||
<< " to " << modestring[to] << std::endl;
|
||||
OpmLog::info(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Destructor send does the actual logging.
|
||||
~WellSwitchingLogger();
|
||||
|
||||
private:
|
||||
|
||||
#if HAVE_MPI
|
||||
void unpackDataAndLog(std::vector<char>& recv_buffer,
|
||||
const std::vector<int>& displ);
|
||||
|
||||
void packData(std::vector<int>& well_name_length,
|
||||
std::vector<char>& buffer);
|
||||
|
||||
int calculateMessageSize(std::vector<int>& well_name_length);
|
||||
|
||||
void logSwitch(const char* name, std::array<char,2> fromto,
|
||||
int rank);
|
||||
|
||||
#endif // HAVE_MPI
|
||||
|
||||
void gatherDataAndLog();
|
||||
|
||||
/// \brief A map containing the local switches
|
||||
SwitchMap switchMap_;
|
||||
/// \brief Collective communication object.
|
||||
Communication cc_;
|
||||
/// \brief The strings for printing.
|
||||
const std::string modestring[4] = { "BHP", "THP", "RESERVOIR_RATE", "SURFACE_RATE" };
|
||||
};
|
||||
} // end namespace wellhelpers
|
||||
} // end namespace Opm
|
||||
#endif
|
||||
65
tests/test_wellswitchlogger.cpp
Normal file
65
tests/test_wellswitchlogger.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include <config.h>
|
||||
#include <dune/common/version.hh>
|
||||
|
||||
#if HAVE_DYNAMIC_BOOST_TEST
|
||||
#define BOOST_TEST_DYN_LINK
|
||||
#endif
|
||||
#define BOOST_TEST_MODULE DistributedCpGridTests
|
||||
#define BOOST_TEST_NO_MAIN
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <opm/simulators/WellSwitchingLogger.hpp>
|
||||
|
||||
#if HAVE_MPI
|
||||
class MPIError {
|
||||
public:
|
||||
/** @brief Constructor. */
|
||||
MPIError(std::string s, int e) : errorstring(s), errorcode(e){}
|
||||
/** @brief The error string. */
|
||||
std::string errorstring;
|
||||
/** @brief The mpi error code. */
|
||||
int errorcode;
|
||||
};
|
||||
|
||||
void MPI_err_handler(MPI_Comm *, int *err_code, ...){
|
||||
char *err_string=new char[MPI_MAX_ERROR_STRING];
|
||||
int err_length;
|
||||
MPI_Error_string(*err_code, err_string, &err_length);
|
||||
std::string s(err_string, err_length);
|
||||
std::cerr << "An MPI Error ocurred:"<<std::endl<<s<<std::endl;
|
||||
delete[] err_string;
|
||||
throw MPIError(s, *err_code);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
init_unit_test_func()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
BOOST_AUTO_TEST_CASE(wellswitchlog)
|
||||
{
|
||||
auto cc = Dune::MPIHelper::getCollectiveCommunication();
|
||||
|
||||
Opm::wellhelpers::WellSwitchingLogger logger(cc);
|
||||
std::ostringstream name;
|
||||
name <<"Well on rank "<<cc.rank()<<std::flush;
|
||||
|
||||
logger.wellSwitched(name.str(), BHP, THP);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Dune::MPIHelper::instance(argc, argv);
|
||||
#if HAVE_MPI
|
||||
// register a throwing error handler to allow for
|
||||
// debugging with "catch throw" in gdb
|
||||
MPI_Errhandler handler;
|
||||
MPI_Comm_create_errhandler(MPI_err_handler, &handler);
|
||||
MPI_Comm_set_errhandler(MPI_COMM_WORLD, handler);
|
||||
#endif
|
||||
boost::unit_test::unit_test_main(&init_unit_test_func,
|
||||
argc, argv);
|
||||
}
|
||||
Reference in New Issue
Block a user