source: XIOS/trunk/src/filter/spatial_transform_filter.cpp @ 709

Last change on this file since 709 was 709, checked in by mhnguyen, 9 years ago

Correcting a bug in interpolation domain

+) Replace shared send buffer by seperate buffer for each proc
+) Remove some redundant codes

Test
+) On Curie
+) test_client, test_complete and test_remap pass

File size: 6.4 KB
Line 
1#include "spatial_transform_filter.hpp"
2#include "grid_transformation.hpp"
3#include "context.hpp"
4#include "context_client.hpp"
5
6namespace xios
7{
8  CSpatialTransformFilter::CSpatialTransformFilter(CGarbageCollector& gc, CSpatialTransformFilterEngine* engine)
9    : CFilter(gc, 1, engine)
10  { /* Nothing to do */ }
11
12  std::pair<boost::shared_ptr<CSpatialTransformFilter>, boost::shared_ptr<CSpatialTransformFilter> >
13  CSpatialTransformFilter::buildFilterGraph(CGarbageCollector& gc, CGrid* srcGrid, CGrid* destGrid)
14  {
15    if (!srcGrid || !destGrid)
16      ERROR("std::pair<boost::shared_ptr<CSpatialTransformFilter>, boost::shared_ptr<CSpatialTransformFilter> >"
17            "buildFilterGraph(CGarbageCollector& gc, CGrid* srcGrid, CGrid* destGrid)",
18            "Impossible to build the filter graph if either the source or the destination grid are null.");
19
20    // TODO: Implement the real path finding algorithm after a solution has been found
21    //       to support initializing grid transformations during parsing.
22    CSpatialTransformFilterEngine* engine = CSpatialTransformFilterEngine::get(destGrid->getTransformations());
23    boost::shared_ptr<CSpatialTransformFilter> filter(new CSpatialTransformFilter(gc, engine));
24
25    return std::make_pair(filter, filter);
26  }
27
28  CSpatialTransformFilterEngine::CSpatialTransformFilterEngine(CGridTransformation* gridTransformation)
29    : gridTransformation(gridTransformation)
30  {
31    if (!gridTransformation)
32      ERROR("CSpatialTransformFilterEngine::CSpatialTransformFilterEngine(CGridTransformation* gridTransformation)",
33            "Impossible to construct a spatial transform filter engine without a valid grid transformation.");
34  }
35
36  std::map<CGridTransformation*, boost::shared_ptr<CSpatialTransformFilterEngine> > CSpatialTransformFilterEngine::engines;
37
38  CSpatialTransformFilterEngine* CSpatialTransformFilterEngine::get(CGridTransformation* gridTransformation)
39  {
40    if (!gridTransformation)
41      ERROR("CSpatialTransformFilterEngine& CSpatialTransformFilterEngine::get(CGridTransformation* gridTransformation)",
42            "Impossible to get the requested engine, the grid transformation is invalid.");
43
44    std::map<CGridTransformation*, boost::shared_ptr<CSpatialTransformFilterEngine> >::iterator it = engines.find(gridTransformation);
45    if (it == engines.end())
46    {
47      boost::shared_ptr<CSpatialTransformFilterEngine> engine(new CSpatialTransformFilterEngine(gridTransformation));
48      it = engines.insert(std::make_pair(gridTransformation, engine)).first;
49    }
50
51    return it->second.get();
52  }
53
54  CDataPacketPtr CSpatialTransformFilterEngine::apply(std::vector<CDataPacketPtr> data)
55  {
56    CDataPacketPtr packet(new CDataPacket);
57    packet->date = data[0]->date;
58    packet->timestamp = data[0]->timestamp;
59    packet->status = data[0]->status;
60
61    if (packet->status == CDataPacket::NO_ERROR)
62    {
63      packet->data.resize(gridTransformation->getGridDestination()->storeIndex_client.numElements());
64      apply(data[0]->data, packet->data);
65    }
66
67    return packet;
68  }
69
70  void CSpatialTransformFilterEngine::apply(const CArray<double, 1>& dataSrc, CArray<double,1>& dataDest)
71  {
72    CContextClient* client = CContext::getCurrent()->client;
73
74    const std::map<int, CArray<int,1> >& localIndexToSend = gridTransformation->getLocalIndexToSendFromGridSource();
75    const std::map<int, std::vector<std::vector<std::pair<int,double> > > >& localIndexToReceive = gridTransformation->getLocalIndexToReceiveOnGridDest();
76
77    dataDest = 0.0;
78
79    // Sending data from field sources to do transformations
80    std::map<int, CArray<int,1> >::const_iterator itbSend = localIndexToSend.begin(), itSend,
81                                                  iteSend = localIndexToSend.end();
82    int idxSendBuff = 0;
83    std::vector<double*> sendBuff(localIndexToSend.size());
84    for (itSend = itbSend; itSend != iteSend; ++itSend, ++idxSendBuff)
85    {
86      if (0 != itSend->second.numElements())
87        sendBuff[idxSendBuff] = new double[itSend->second.numElements()];
88    }
89
90    idxSendBuff = 0;
91    std::vector<MPI_Request> sendRequest;
92    for (itSend = itbSend; itSend != iteSend; ++itSend, ++idxSendBuff)
93    {
94      int destRank = itSend->first;
95      const CArray<int,1>& localIndex_p = itSend->second;
96      int countSize = localIndex_p.numElements();
97      for (int idx = 0; idx < countSize; ++idx)
98      {
99        sendBuff[idxSendBuff][idx] = dataSrc(localIndex_p(idx));
100      }
101      sendRequest.push_back(MPI_Request());
102      MPI_Isend(sendBuff[idxSendBuff], countSize, MPI_DOUBLE, destRank, 12, client->intraComm, &sendRequest.back());
103    }
104
105    // Receiving data on destination fields
106    std::map<int,std::vector<std::vector<std::pair<int,double> > > >::const_iterator itbRecv = localIndexToReceive.begin(), itRecv,
107                                                                                     iteRecv = localIndexToReceive.end();
108    int recvBuffSize = 0;
109    for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv) recvBuffSize = (recvBuffSize < itRecv->second.size())
110                                                                     ? itRecv->second.size() : recvBuffSize;
111    double* recvBuff;
112    if (0 != recvBuffSize) recvBuff = new double[recvBuffSize];
113    for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
114    {
115      MPI_Status status;
116      int srcRank = itRecv->first;
117      int countSize = itRecv->second.size();
118      MPI_Recv(recvBuff, recvBuffSize, MPI_DOUBLE, srcRank, 12, client->intraComm, &status);
119      int countBuff = 0;
120      MPI_Get_count(&status, MPI_DOUBLE, &countBuff);
121      if (countBuff != countSize)
122        ERROR("CSpatialTransformFilterEngine::apply(const CArray<double, 1>& dataSrc, CArray<double,1>& dataDest)",
123              "Incoherent between the received size and expected size");
124      for (int idx = 0; idx < countSize; ++idx)
125      {
126        const std::vector<std::pair<int,double> >& localIndex_p = itRecv->second[idx];
127        int numIndex = localIndex_p.size();
128        for (int i = 0; i < numIndex; ++i)
129        {
130          dataDest(localIndex_p[i].first) += recvBuff[idx] * localIndex_p[i].second;
131        }
132      }
133    }
134
135
136    if (!sendRequest.empty()) MPI_Waitall(sendRequest.size(), &sendRequest[0], MPI_STATUSES_IGNORE);
137    idxSendBuff = 0;
138    for (itSend = itbSend; itSend != iteSend; ++itSend, ++idxSendBuff)
139    {
140      if (0 != itSend->second.numElements())
141        delete [] sendBuff[idxSendBuff];
142    }
143    if (0 != recvBuffSize) delete [] recvBuff;
144  }
145} // namespace xios
Note: See TracBrowser for help on using the repository browser.