replace well switching logger with deferred logger

This commit is contained in:
Franz G. Fuchs 2019-01-18 14:04:30 +01:00
parent 1b79501060
commit 129e7d181e
14 changed files with 67 additions and 440 deletions

View File

@ -39,7 +39,6 @@ list (APPEND MAIN_SOURCE_FILES
opm/core/wells/WellsManager.cpp
opm/core/wells/well_controls.c
opm/core/wells/wells.c
opm/simulators/WellSwitchingLogger.cpp
opm/simulators/DeferredLogger.cpp
opm/simulators/timestepping/TimeStepControl.cpp
opm/simulators/timestepping/AdaptiveSimulatorTimer.cpp
@ -58,7 +57,6 @@ list (APPEND TEST_SOURCE_FILES
tests/test_milu.cpp
tests/test_multmatrixtransposed.cpp
tests/test_wellmodel.cpp
tests/test_wellswitchlogger.cpp
tests/test_deferredlogger.cpp
tests/test_timer.cpp
tests/test_invert.cpp
@ -165,7 +163,6 @@ list (APPEND PUBLIC_HEADER_FILES
opm/core/wells/WellsManager.hpp
opm/core/wells/WellsManager_impl.hpp
opm/simulators/ParallelFileMerger.hpp
opm/simulators/WellSwitchingLogger.hpp
opm/simulators/DeferredLogger.hpp
opm/simulators/timestepping/AdaptiveSimulatorTimer.hpp
opm/simulators/timestepping/AdaptiveTimeSteppingEbos.hpp

View File

@ -56,7 +56,7 @@
#include <opm/material/densead/Math.hpp>
#include <opm/simulators/WellSwitchingLogger.hpp>
#include <opm/simulators/DeferredLogger.hpp>
BEGIN_PROPERTIES

View File

@ -320,7 +320,7 @@ namespace Opm {
// no wells needing testing, otherwise we will have locking.
std::vector< Scalar > B_avg(numComponents(), Scalar() );
computeAverageFormationFactor(B_avg);
wellhelpers::WellSwitchingLogger logger;
Opm::DeferredLogger local_deferredLogger;
const auto& wellsForTesting = wellTestState_.updateWell(wtest_config, simulationTime);
for (const auto& testWell : wellsForTesting) {
@ -338,8 +338,12 @@ namespace Opm {
const WellTestConfig::Reason testing_reason = testWell.second;
well->wellTesting(ebosSimulator_, B_avg, simulationTime, timeStepIdx, terminal_output_,
testing_reason, well_state_, wellTestState_, logger);
well->wellTesting(ebosSimulator_, B_avg, simulationTime, timeStepIdx,
testing_reason, well_state_, wellTestState_, local_deferredLogger);
}
Opm::DeferredLogger global_deferredLogger = gatherDeferredLogger(local_deferredLogger);
if (terminal_output_) {
global_deferredLogger.logMessages();
}
}
@ -936,15 +940,20 @@ namespace Opm {
updateWellControls()
{
// Even if there no wells active locally, we cannot
// return as the Destructor of the WellSwitchingLogger
// return as the Destructor of the DeferredLogger
// uses global communication. For no well active globally
// we simply return.
if( !wellsActive() ) return ;
wellhelpers::WellSwitchingLogger logger;
Opm::DeferredLogger local_deferredLogger;
for (const auto& well : well_container_) {
well->updateWellControl(ebosSimulator_, well_state_, logger);
well->updateWellControl(ebosSimulator_, well_state_, local_deferredLogger);
}
Opm::DeferredLogger global_deferredLogger = gatherDeferredLogger(local_deferredLogger);
if (terminal_output_) {
global_deferredLogger.logMessages();
}
updateGroupControls();

View File

@ -352,8 +352,7 @@ namespace Opm
virtual void wellTestingPhysical(Simulator& simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step,
const bool terminal_output,
WellState& well_state, WellTestState& welltest_state, wellhelpers::WellSwitchingLogger& logger) override;
WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferredLogger) override;
virtual void updateWaterThroughput(const double dt, WellState& well_state) const override;
};

View File

@ -1896,8 +1896,8 @@ namespace Opm
void
MultisegmentWell<TypeTag>::
wellTestingPhysical(Simulator& simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const bool terminal_output,
WellState& well_state, WellTestState& welltest_state, wellhelpers::WellSwitchingLogger& logger)
const double simulation_time, const int report_step,
WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferredLogger)
{
const std::string msg = "Support of well testing for physical limits for multisegment wells is not "
"implemented yet, wellTestingPhysical() for " + name() + " will do nothing";

View File

@ -413,8 +413,8 @@ namespace Opm
const BVectorWell& dwells);
virtual void wellTestingPhysical(Simulator& simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const bool terminal_output,
WellState& well_state, WellTestState& welltest_state, wellhelpers::WellSwitchingLogger& logger) override;
const double simulation_time, const int report_step,
WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferredLogger) override;
virtual void updateWaterThroughput(const double dt, WellState& well_state) const override;
};

View File

@ -418,8 +418,8 @@ namespace Opm
const BVectorWell& dwells);
virtual void wellTestingPhysical(Simulator& simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const bool terminal_output,
WellState& well_state, WellTestState& welltest_state, wellhelpers::WellSwitchingLogger& logger) override;
const double simulation_time, const int report_step,
WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferredLogger) override;
// calculate the skin pressure based on water velocity, throughput and polymer concentration.
// throughput is used to describe the formation damage during water/polymer injection.

View File

@ -2867,8 +2867,8 @@ namespace Opm
void
StandardWellV<TypeTag>::
wellTestingPhysical(Simulator& ebos_simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const bool terminal_output,
WellState& well_state, WellTestState& welltest_state, wellhelpers::WellSwitchingLogger& logger)
const double simulation_time, const int report_step,
WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferredLogger)
{
OpmLog::debug(" well " + name() + " is being tested for physical limits");
@ -2903,7 +2903,7 @@ namespace Opm
updatePrimaryVariables(well_state_copy);
initPrimaryVariablesEvaluation();
const bool converged = this->solveWellEqUntilConverged(ebos_simulator, B_avg, well_state_copy, logger);
const bool converged = this->solveWellEqUntilConverged(ebos_simulator, B_avg, well_state_copy, deferredLogger);
if (!converged) {
const std::string msg = " well " + name() + " did not get converged during well testing for physical reason";

View File

@ -2747,8 +2747,8 @@ namespace Opm
void
StandardWell<TypeTag>::
wellTestingPhysical(Simulator& ebos_simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const bool terminal_output,
WellState& well_state, WellTestState& welltest_state, wellhelpers::WellSwitchingLogger& logger)
const double simulation_time, const int report_step,
WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferredLogger)
{
OpmLog::debug(" well " + name() + " is being tested for physical limits");
@ -2783,7 +2783,7 @@ namespace Opm
updatePrimaryVariables(well_state_copy);
initPrimaryVariablesEvaluation();
const bool converged = this->solveWellEqUntilConverged(ebos_simulator, B_avg, well_state_copy, logger);
const bool converged = this->solveWellEqUntilConverged(ebos_simulator, B_avg, well_state_copy, deferredLogger);
if (!converged) {
const std::string msg = " well " + name() + " did not get converged during well testing for physical reason";

View File

@ -45,7 +45,7 @@
#include <opm/autodiff/RateConverter.hpp>
#include <opm/simulators/timestepping/ConvergenceReport.hpp>
#include <opm/simulators/WellSwitchingLogger.hpp>
#include <opm/simulators/DeferredLogger.hpp>
#include<dune/common/fmatrix.hh>
#include<dune/istl/bcrsmatrix.hh>
@ -183,7 +183,7 @@ namespace Opm
void updateWellControl(/* const */ Simulator& ebos_simulator,
WellState& well_state,
wellhelpers::WellSwitchingLogger& logger) /* const */;
Opm::DeferredLogger& deferredLogger) /* const */;
virtual void updatePrimaryVariables(const WellState& well_state) const = 0;
@ -226,10 +226,10 @@ namespace Opm
// TODO: theoretically, it should be a const function
// Simulator is not const is because that assembleWellEq is non-const Simulator
void wellTesting(Simulator& simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const bool terminal_output,
const double simulation_time, const int report_step,
const WellTestConfig::Reason testing_reason,
/* const */ WellState& well_state, WellTestState& welltest_state,
wellhelpers::WellSwitchingLogger& logger);
Opm::DeferredLogger& deferredLogger);
void updatePerforatedCell(std::vector<bool>& is_cell_perforated);
@ -374,12 +374,12 @@ namespace Opm
OperabilityStatus operability_status_;
void wellTestingEconomic(Simulator& simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const bool terminal_output,
const WellState& well_state, WellTestState& welltest_state, wellhelpers::WellSwitchingLogger& logger);
const double simulation_time, const int report_step,
const WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferredLogger);
virtual void wellTestingPhysical(Simulator& simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const bool terminal_output,
WellState& well_state, WellTestState& welltest_state, wellhelpers::WellSwitchingLogger& logger) = 0;
const double simulation_time, const int report_step,
WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferredLogger) = 0;
void updateWellTestStateEconomic(const WellState& well_state,
const double simulation_time,
@ -392,13 +392,13 @@ namespace Opm
WellTestState& well_test_state) const;
void solveWellForTesting(Simulator& ebosSimulator, WellState& well_state,
const std::vector<double>& B_avg, bool terminal_output,
wellhelpers::WellSwitchingLogger& logger);
const std::vector<double>& B_avg,
Opm::DeferredLogger& deferredLogger);
bool solveWellEqUntilConverged(Simulator& ebosSimulator,
const std::vector<double>& B_avg,
WellState& well_state,
wellhelpers::WellSwitchingLogger& logger);
Opm::DeferredLogger& deferredLogger);
void scaleProductivityIndex(const int perfIdx, double& productivity_index);
@ -453,6 +453,7 @@ namespace Opm
bool obey_bhp_limit_with_thp_limit = true;
};
const std::string modestring[4] = { "BHP", "THP", "RESERVOIR_RATE", "SURFACE_RATE" };
}

View File

@ -431,7 +431,7 @@ namespace Opm
WellInterface<TypeTag>::
updateWellControl(/* const */ Simulator& ebos_simulator,
WellState& well_state,
wellhelpers::WellSwitchingLogger& logger) /* const */
Opm::DeferredLogger& deferredLogger) /* const */
{
const int np = number_of_phases_;
const int w = index_of_well_;
@ -493,9 +493,15 @@ namespace Opm
// checking whether control changed
if (updated_control_index != old_control_index) {
logger.wellSwitched(name(),
well_controls_iget_type(wc, old_control_index),
well_controls_iget_type(wc, updated_control_index));
auto from = well_controls_iget_type(wc, old_control_index);
auto to = well_controls_iget_type(wc, updated_control_index);
std::ostringstream ss;
ss << " Switching control mode for well " << name()
<< " from " << modestring[from]
<< " to " << modestring[to];
deferredLogger.info(ss.str());
//logger.wellSwitched(name()
}
if (updated_control_index != old_control_index) { // || well_collection_->groupControlActive()) {
@ -924,20 +930,20 @@ namespace Opm
void
WellInterface<TypeTag>::
wellTesting(Simulator& simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const bool terminal_output,
const double simulation_time, const int report_step,
const WellTestConfig::Reason testing_reason,
/* const */ WellState& well_state,
WellTestState& well_test_state,
wellhelpers::WellSwitchingLogger& logger)
Opm::DeferredLogger& deferredLogger)
{
if (testing_reason == WellTestConfig::Reason::PHYSICAL) {
wellTestingPhysical(simulator, B_avg, simulation_time, report_step,
terminal_output, well_state, well_test_state, logger);
well_state, well_test_state, deferredLogger);
}
if (testing_reason == WellTestConfig::Reason::ECONOMIC) {
wellTestingEconomic(simulator, B_avg, simulation_time, report_step,
terminal_output, well_state, well_test_state, logger);
well_state, well_test_state, deferredLogger);
}
}
@ -949,8 +955,8 @@ namespace Opm
void
WellInterface<TypeTag>::
wellTestingEconomic(Simulator& simulator, const std::vector<double>& B_avg,
const double simulation_time, const int report_step, const bool terminal_output,
const WellState& well_state, WellTestState& welltest_state, wellhelpers::WellSwitchingLogger& logger)
const double simulation_time, const int report_step,
const WellState& well_state, WellTestState& welltest_state, Opm::DeferredLogger& deferredLogger)
{
OpmLog::debug(" well " + name() + " is being tested for economic limits");
@ -968,7 +974,7 @@ namespace Opm
// untill the number of closed completions do not increase anymore.
while (testWell) {
const size_t original_number_closed_completions = welltest_state_temp.sizeCompletions();
solveWellForTesting(simulator, well_state_copy, B_avg, terminal_output, logger);
solveWellForTesting(simulator, well_state_copy, B_avg, deferredLogger);
updateWellTestState(well_state_copy, simulation_time, /*writeMessageToOPMLog=*/ false, welltest_state_temp);
closeCompletions(welltest_state_temp);
@ -1156,7 +1162,7 @@ namespace Opm
solveWellEqUntilConverged(Simulator& ebosSimulator,
const std::vector<double>& B_avg,
WellState& well_state,
wellhelpers::WellSwitchingLogger& logger)
Opm::DeferredLogger& deferredLogger)
{
const int max_iter = param_.max_welleq_iter_;
int it = 0;
@ -1175,7 +1181,7 @@ namespace Opm
++it;
solveEqAndUpdateWellState(well_state);
updateWellControl(ebosSimulator, well_state, logger);
updateWellControl(ebosSimulator, well_state, deferredLogger);
initPrimaryVariablesEvaluation();
} while (it < max_iter);
@ -1225,22 +1231,18 @@ namespace Opm
void
WellInterface<TypeTag>::
solveWellForTesting(Simulator& ebosSimulator, WellState& well_state,
const std::vector<double>& B_avg, bool terminal_output,
wellhelpers::WellSwitchingLogger& logger)
const std::vector<double>& B_avg,
Opm::DeferredLogger& deferredLogger)
{
// keep a copy of the original well state
const WellState well_state0 = well_state;
const bool converged = solveWellEqUntilConverged(ebosSimulator, B_avg, well_state, logger);
const bool converged = solveWellEqUntilConverged(ebosSimulator, B_avg, well_state, deferredLogger);
if (converged) {
if ( terminal_output ) {
OpmLog::debug("WellTest: Well equation for well " + name() + " solution gets converged");
}
OpmLog::debug("WellTest: Well equation for well " + name() + " solution gets converged");
} else {
if ( terminal_output ) {
const int max_iter = param_.max_welleq_iter_;
OpmLog::debug("WellTest: Well equation for well" +name() + " solution failed in getting converged with "
+ std::to_string(max_iter) + " iterations");
}
const int max_iter = param_.max_welleq_iter_;
OpmLog::debug("WellTest: Well equation for well" +name() + " solution failed in getting converged with "
+ std::to_string(max_iter) + " iterations");
well_state = well_state0;
}
}

View File

@ -1,205 +0,0 @@
/*
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/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H
#include <opm/simulators/WellSwitchingLogger.hpp>
#include <numeric>
namespace Opm
{
namespace wellhelpers
{
#if HAVE_MPI
int WellSwitchingLogger::calculateMessageSize(std::vector<int>& well_name_lengths)
{
// 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_lengths.reserve(switchMap_.size());
for(const auto& switchEntry : switchMap_)
{
int length = switchEntry.first.size() +1; //we write an additional \0
well_name_lengths.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);
// 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
for(const auto& length : well_name_lengths)
{
// 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;
}
return message_size;
}
void WellSwitchingLogger::packData(std::vector<int>& well_name_lengths,
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_lengths.data(), well_name_lengths.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_lengths(no_switches);
MPI_Unpack(recv_buffer.data(), recv_buffer.size(), &offset,
well_name_lengths.data(), well_name_lengths.size(),
MPI_INT, MPI_COMM_WORLD);
std::vector<char> well_name;
for ( int i = 0; i < no_switches; ++i )
{
well_name.resize(well_name_lengths[i]);
MPI_Unpack(recv_buffer.data(), recv_buffer.size(), &offset,
well_name.data(), well_name_lengths[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.data(), 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;
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_lengths;
int message_size = calculateMessageSize(well_name_lengths);
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_lengths, 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

View File

@ -1,114 +0,0 @@
/*
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 <array>
#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 =
Dune::MPIHelper::getCollectiveCommunication())
: 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];
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

View File

@ -1,62 +0,0 @@
#include <config.h>
#include <dune/common/version.hh>
#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
return boost::unit_test::unit_test_main(&init_unit_test_func,
argc, argv);
}