mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
replace well switching logger with deferred logger
This commit is contained in:
parent
1b79501060
commit
129e7d181e
@ -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
|
||||
|
@ -56,7 +56,7 @@
|
||||
|
||||
#include <opm/material/densead/Math.hpp>
|
||||
|
||||
#include <opm/simulators/WellSwitchingLogger.hpp>
|
||||
#include <opm/simulators/DeferredLogger.hpp>
|
||||
|
||||
BEGIN_PROPERTIES
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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.
|
||||
|
@ -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";
|
||||
|
@ -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";
|
||||
|
@ -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" };
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -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
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user