File: SimulateStepTreeDist.cpp

package info (click to toggle)
stopt 5.12%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 8,860 kB
  • sloc: cpp: 70,456; python: 5,950; makefile: 72; sh: 57
file content (150 lines) | stat: -rw-r--r-- 7,818 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright (C) 2019 EDF
// All Rights Reserved
// This code is published under the GNU Lesser General Public License (GNU LGPL)
#ifdef USE_MPI
#include "geners/Reference.hh"
#include "geners/vectorIO.hh"
#include "StOpt/dp/SimulateStepTreeDist.h"
#include "StOpt/core/utils/eigenGeners.h"
#include "StOpt/core/utils/primeNumber.h"
#include "StOpt/core/utils/NodeParticleSplitting.h"
#include "StOpt/core/utils/types.h"
#include "StOpt/core/parallelism/all_gatherv.hpp"

using namespace std;
using namespace StOpt;
using namespace Eigen;


SimulateStepTreeDist::SimulateStepTreeDist(gs::BinaryFileArchive &p_ar,  const int &p_iStep,  const string &p_nameCont,
        const   shared_ptr<FullGrid> &p_pGridFollowing, const  shared_ptr<OptimizerDPTreeBase > &p_pOptimize,
        const bool &p_bOneFile, const boost::mpi::communicator &p_world): m_pGridFollowing(p_pGridFollowing),
    m_pOptimize(p_pOptimize), m_contValue(p_pOptimize->getNbRegime()), m_bOneFile(p_bOneFile)	, m_world(p_world)
{
    string stepString = boost::lexical_cast<string>(p_iStep);
    if (m_bOneFile)
    {
        gs::Reference< vector< GridTreeValue> >(p_ar, (p_nameCont + "Values").c_str(), stepString.c_str()).restore(0, &m_continuationObj);
    }
    else
    {
        vector<int> initialVecDimensionFollow;
        gs::Reference< 	vector<int> >(p_ar, "initialSizeOfMeshPrev", stepString.c_str()).restore(0, &initialVecDimensionFollow);
        Map<const ArrayXi > initialDimensionFollow(initialVecDimensionFollow.data(), initialVecDimensionFollow.size());
        ArrayXi splittingRatio = paraOptimalSplitting(initialDimensionFollow, m_pOptimize->getDimensionToSplit(), p_world);
        m_parall =  make_shared<ParallelComputeGridSplitting>(initialDimensionFollow, splittingRatio, p_world);
        gs::Reference< vector<ArrayXXd  > >(p_ar, (p_nameCont + "Values").c_str(), stepString.c_str()).restore(0, & m_contValue);
    }
}

void SimulateStepTreeDist::oneStep(vector<StateTreeStocks > &p_statevector, ArrayXXd  &p_phiInOut) const
{
    unique_ptr<ArrayXXd >  particles(new ArrayXXd(p_statevector.size(), m_pGridFollowing->getDimension()));
    for (size_t is = 0; is < p_statevector.size(); ++is)
        for (int isto = 0; isto < m_pGridFollowing->getDimension(); ++isto)
            (*particles)(is, isto) = p_statevector[is].getPtStock()(isto);
    ArrayXi splittingRatio = ArrayXi::Constant(m_pGridFollowing->getDimension(), 1);
    vector<int> prime = primeNumber(m_world.size());
    int idim = 0; // roll the dimensions
    for (size_t i = 0; i < prime.size(); ++i)
    {
        splittingRatio(idim % m_pGridFollowing->getDimension()) *= prime[i];
        idim += 1;
    }
    // create object to split particules on processor
    NodeParticleSplitting splitparticle(particles, splittingRatio);
    // each simulation to a cell
    ArrayXi nCell(p_statevector.size());
    Array<  array<double, 2 >, Dynamic, Dynamic > meshToCoord(m_pGridFollowing->getDimension(), m_world.size());
    splitparticle.simToCell(nCell, meshToCoord);
    // simulation for current processor
    vector< int > simCurrentProc;
    simCurrentProc.reserve(2 * p_statevector.size() / m_world.size()) ; // use a margin
    for (size_t is = 0; is <  p_statevector.size(); ++is)
        if (nCell(is) == m_world.rank())
            simCurrentProc.push_back(is);
    // nows store stocks
    ArrayXd stockPerSim(m_pGridFollowing->getDimension()*simCurrentProc.size());
    // nows store regimes
    ArrayXi regimePerSim(simCurrentProc.size());
    // store value functions
    ArrayXXd valueFunctionPerSim(m_pOptimize->getSimuFuncSize(), simCurrentProc.size());
    if (m_bOneFile)
    {
        // spread calculations on processors
        for (size_t is = 0; is <  simCurrentProc.size(); ++is)
        {
            int simuNumber = simCurrentProc[is];
            m_pOptimize->stepSimulate(m_pGridFollowing, m_continuationObj, p_statevector[simuNumber], p_phiInOut.col(simuNumber));
            // store for broadcast
            stockPerSim.segment(is * m_pGridFollowing->getDimension(), m_pGridFollowing->getDimension()) = p_statevector[simuNumber].getPtStock();
            regimePerSim(is) = p_statevector[simuNumber].getRegime();
            if (valueFunctionPerSim.size() > 0)
                valueFunctionPerSim.col(is) = p_phiInOut.col(simuNumber);
        }
    }
    else
    {
        // calculate extended grids
        vector<  array< double, 2>  >  regionByProcessor(splittingRatio.size());
        for (int id = 0; id < splittingRatio.size() ; ++id)
            regionByProcessor[id] = meshToCoord(id, m_world.rank());
        vector<  array< double, 2>  > cone = m_pOptimize->getCone(regionByProcessor);
        // now get subgrid correspond to the cone
        SubMeshIntCoord retGrid(m_pGridFollowing->getDimension());
        vector <array< double, 2>  > extremVal =  m_pGridFollowing->getExtremeValues();
        ArrayXd xCapMin(m_pGridFollowing->getDimension()), xCapMax(m_pGridFollowing->getDimension());
        for (int id = 0; id <  m_pGridFollowing->getDimension(); ++id)
        {
            xCapMin(id)   = max(cone[id][0], extremVal[id][0]);
            xCapMax(id)  = min(cone[id][1], extremVal[id][1]);
        }
        ArrayXi  iCapMin =  m_pGridFollowing->lowerPositionCoord(xCapMin);
        ArrayXi  iCapMax =  m_pGridFollowing->upperPositionCoord(xCapMax) + 1; // last is excluded
        for (int id = 0; id <  m_pGridFollowing->getDimension(); ++id)
        {
            retGrid(id)[0] = iCapMin(id);
            retGrid(id)[1] = iCapMax(id);
        }
        // extend continuation values
        shared_ptr<FullGrid> gridExtended = m_pGridFollowing->getSubGrid(retGrid);
        vector< GridTreeValue >  continuationExtended(m_pOptimize->getNbRegime());
        for (int iReg = 0; iReg < m_pOptimize->getNbRegime(); ++iReg)
        {
            ArrayXXd valuesExtended = m_parall->reconstructAll<double>(m_contValue[iReg], retGrid);
            continuationExtended[iReg] = GridTreeValue(gridExtended, valuesExtended);
        }
        // spread calculations on processors
        for (size_t is = 0; is <  simCurrentProc.size(); ++is)
        {
            int simuNumber = simCurrentProc[is];
            m_pOptimize->stepSimulate(m_pGridFollowing, continuationExtended,  p_statevector[simuNumber], p_phiInOut.col(simuNumber));
            // store for broadcast
            stockPerSim.segment(is * m_pGridFollowing->getDimension(), m_pGridFollowing->getDimension()) = p_statevector[simuNumber].getPtStock();
            regimePerSim(is) = p_statevector[simuNumber].getRegime();
            if (valueFunctionPerSim.size() > 0)
                valueFunctionPerSim.col(is) = p_phiInOut.col(simuNumber);
        }
    }
    // broadcast
    vector<double> stockAllSim;
    boost::mpi::all_gatherv<double>(m_world, stockPerSim.data(), stockPerSim.size(), stockAllSim);
    vector<int> regimeAllSim;
    boost::mpi::all_gatherv<int>(m_world, regimePerSim.data(), regimePerSim.size(), regimeAllSim);
    vector<double> valueFunctionAllSim;
    boost::mpi::all_gatherv<double>(m_world, valueFunctionPerSim.data(), valueFunctionPerSim.size(), valueFunctionAllSim);
    vector<int> simAllProc;
    boost::mpi::all_gatherv<int>(m_world, simCurrentProc.data(), simCurrentProc.size(), simAllProc);
    // update results
    int iis = 0;
    for (size_t is = 0; is < simAllProc.size(); ++is)
    {
        for (int iid = 0; iid < m_pOptimize->getSimuFuncSize(); ++iid)
            p_phiInOut(iid, simAllProc[is]) = valueFunctionAllSim[iis++];
        Map<const ArrayXd >  ptStock(&stockAllSim[is * m_pGridFollowing->getDimension()], m_pGridFollowing->getDimension());
        p_statevector[simAllProc[is]].setPtStock(ptStock);
        p_statevector[simAllProc[is]].setRegime(regimeAllSim[is]);
    }

}
#endif