mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-09-05 04:40:19 -05:00
Added factory to construct the global representation of perf data.
Some of our computations are heavily serial and need a complete representation of the data attached to all perforation no matter whether a perforation lives on the local partition or not. This commit adds a factory that allows to easily create such a representaion and helps writing data back to the local representation.
This commit is contained in:
@@ -23,6 +23,9 @@
|
||||
#include<string>
|
||||
#include<tuple>
|
||||
#include<ostream>
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#define BOOST_TEST_MODULE ParallelWellInfo
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@@ -96,6 +99,8 @@ std::ostream& operator<<(std::ostream& os, const Opm::ParallelWellInfo& w)
|
||||
}
|
||||
}
|
||||
|
||||
constexpr int numPerProc = 3;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ParallelWellComparison)
|
||||
{
|
||||
int argc = 0;
|
||||
@@ -232,7 +237,7 @@ std::vector<int> createGlobalEclIndex(const Communication& comm)
|
||||
{
|
||||
std::vector<int> globalEclIndex = {0, 1, 2, 3, 7 , 8, 10, 11};
|
||||
auto oldSize = globalEclIndex.size();
|
||||
std::size_t globalSize = 3 * comm.size();
|
||||
std::size_t globalSize = numPerProc * comm.size();
|
||||
auto lastIndex = globalEclIndex.back();
|
||||
globalEclIndex.resize(globalSize);
|
||||
if ( globalSize > oldSize)
|
||||
@@ -251,14 +256,17 @@ template<class C>
|
||||
std::vector<double> populateCommAbove(C& commAboveBelow,
|
||||
const Communication& comm,
|
||||
const std::vector<int>& globalEclIndex,
|
||||
const std::vector<double> globalCurrent)
|
||||
const std::vector<double> globalCurrent,
|
||||
int num_component = 1,
|
||||
bool local_consecutive = false)
|
||||
{
|
||||
std::vector<double> current(3);
|
||||
auto size = numPerProc * num_component;
|
||||
std::vector<double> current(size);
|
||||
|
||||
commAboveBelow.beginReset();
|
||||
for (std::size_t i = 0; i < current.size(); ++i)
|
||||
for (std::size_t i = 0; i < current.size()/num_component; i++)
|
||||
{
|
||||
auto gi = comm.rank() + comm.size() * i;
|
||||
auto gi = local_consecutive ? comm.rank() * numPerProc + i : comm.rank() + comm.size() * i;
|
||||
|
||||
if (gi==0)
|
||||
{
|
||||
@@ -268,7 +276,8 @@ std::vector<double> populateCommAbove(C& commAboveBelow,
|
||||
{
|
||||
commAboveBelow.pushBackEclIndex(globalEclIndex[gi-1], globalEclIndex[gi]);
|
||||
}
|
||||
current[i] = globalCurrent[gi];
|
||||
for(int c = 0; c < num_component; ++c)
|
||||
current[i * num_component + c] = globalCurrent[gi * num_component + c];
|
||||
}
|
||||
commAboveBelow.endReset();
|
||||
return current;
|
||||
@@ -317,3 +326,145 @@ BOOST_AUTO_TEST_CASE(CommunicateAboveBelowParallel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Iter, class C>
|
||||
void initRandomNumbers(Iter begin, Iter end, C comm)
|
||||
{
|
||||
// Initialize with random numbers.
|
||||
std::random_device rndDevice;
|
||||
std::mt19937 mersenneEngine {rndDevice()}; // Generates random integers
|
||||
std::uniform_int_distribution<int> dist {1, 100};
|
||||
|
||||
auto gen = [&dist, &mersenneEngine](){
|
||||
return dist(mersenneEngine);
|
||||
};
|
||||
|
||||
std::generate(begin, end, gen);
|
||||
comm.broadcast(&(*begin), end-begin, 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(PartialSumself)
|
||||
{
|
||||
auto comm = Dune::MPIHelper::getLocalCommunicator();
|
||||
|
||||
Opm::CommunicateAboveBelow commAboveBelow{ comm };
|
||||
std::vector<int> eclIndex = {0, 1, 2, 3, 7 , 8, 10, 11};
|
||||
std::vector<double> current(eclIndex.size());
|
||||
std::transform(eclIndex.begin(), eclIndex.end(), current.begin(),
|
||||
[](double v){ return 1+10.0*v;});
|
||||
commAboveBelow.beginReset();
|
||||
for (std::size_t i = 0; i < current.size(); ++i)
|
||||
{
|
||||
if (i==0)
|
||||
commAboveBelow.pushBackEclIndex(-1, eclIndex[i]);
|
||||
else
|
||||
commAboveBelow.pushBackEclIndex(eclIndex[i-1], eclIndex[i]);
|
||||
}
|
||||
commAboveBelow.endReset();
|
||||
|
||||
initRandomNumbers(std::begin(current), std::end(current),
|
||||
Communication(comm));
|
||||
auto stdCopy = current;
|
||||
std::partial_sum(std::begin(stdCopy), std::end(stdCopy), std::begin(stdCopy));
|
||||
|
||||
|
||||
commAboveBelow.partialSumPerfValues(std::begin(current), std::end(current));
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(stdCopy), std::end(stdCopy),
|
||||
std::begin(current), std::end(current));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(PartialSumParallel)
|
||||
{
|
||||
|
||||
auto comm = Communication(Dune::MPIHelper::getCommunicator());
|
||||
|
||||
Opm::CommunicateAboveBelow commAboveBelow{ comm };
|
||||
auto globalEclIndex = createGlobalEclIndex(comm);
|
||||
std::vector<double> globalCurrent(globalEclIndex.size());
|
||||
initRandomNumbers(std::begin(globalCurrent), std::end(globalCurrent),
|
||||
Communication(comm));
|
||||
|
||||
auto localCurrent = populateCommAbove(commAboveBelow, comm,
|
||||
globalEclIndex, globalCurrent);
|
||||
|
||||
auto globalPartialSum = globalCurrent;
|
||||
|
||||
std::partial_sum(std::begin(globalPartialSum), std::end(globalPartialSum), std::begin(globalPartialSum));
|
||||
|
||||
|
||||
commAboveBelow.partialSumPerfValues(std::begin(localCurrent), std::end(localCurrent));
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < localCurrent.size(); ++i)
|
||||
{
|
||||
auto gi = comm.rank() + comm.size() * i;
|
||||
BOOST_CHECK(localCurrent[i]==globalPartialSum[gi]);
|
||||
}
|
||||
}
|
||||
|
||||
void testGlobalPerfFactoryParallel(int num_component, bool local_consecutive = false)
|
||||
{
|
||||
auto comm = Communication(Dune::MPIHelper::getCommunicator());
|
||||
|
||||
Opm::ParallelWellInfo wellInfo{ {"Test", true }, comm };
|
||||
auto globalEclIndex = createGlobalEclIndex(comm);
|
||||
std::vector<double> globalCurrent(globalEclIndex.size() * num_component);
|
||||
std::vector<double> globalAdd(globalEclIndex.size() * num_component);
|
||||
initRandomNumbers(std::begin(globalCurrent), std::end(globalCurrent),
|
||||
comm);
|
||||
initRandomNumbers(std::begin(globalAdd), std::end(globalAdd),
|
||||
comm);
|
||||
|
||||
auto localCurrent = populateCommAbove(wellInfo, comm, globalEclIndex,
|
||||
globalCurrent, num_component,
|
||||
local_consecutive);
|
||||
|
||||
// A hack to get local values to add.
|
||||
Opm::ParallelWellInfo dummy{ {"Test", true }, comm };
|
||||
auto localAdd = populateCommAbove(dummy, comm, globalEclIndex,
|
||||
globalAdd, num_component,
|
||||
local_consecutive);
|
||||
|
||||
const auto& factory = wellInfo.getGlobalPerfContainerFactory();
|
||||
|
||||
auto globalCreated = factory.createGlobal(localCurrent, num_component);
|
||||
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(globalCurrent), std::end(globalCurrent),
|
||||
std::begin(globalCreated), std::end(globalCreated));
|
||||
|
||||
std::transform(std::begin(globalAdd), std::end(globalAdd),
|
||||
std::begin(globalCreated), std::begin(globalCreated),
|
||||
std::plus<double>());
|
||||
|
||||
auto globalSol = globalCurrent;
|
||||
std::transform(std::begin(globalAdd), std::end(globalAdd),
|
||||
std::begin(globalSol), std::begin(globalSol),
|
||||
std::plus<double>());
|
||||
|
||||
auto localSol = localCurrent;
|
||||
|
||||
std::transform(std::begin(localAdd), std::end(localAdd),
|
||||
std::begin(localSol), std::begin(localSol),
|
||||
std::plus<double>());
|
||||
factory.copyGlobalToLocal(globalCreated, localCurrent, num_component);
|
||||
|
||||
for (std::size_t i = 0; i < localCurrent.size() / num_component; ++i)
|
||||
{
|
||||
auto gi = local_consecutive ? comm.rank() * numPerProc + i :
|
||||
comm.rank() + comm.size() * i;
|
||||
for (int c = 0; c < num_component; ++c)
|
||||
{
|
||||
BOOST_CHECK(localCurrent[i * num_component + c]==globalSol[gi * num_component + c]);
|
||||
BOOST_CHECK(localSol[i * num_component + c] == localCurrent[i * num_component + c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GlobalPerfFactoryParallel1)
|
||||
{
|
||||
|
||||
testGlobalPerfFactoryParallel(1);
|
||||
testGlobalPerfFactoryParallel(3);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user