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

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

Updating some fortran interface

Test
+) On Curie
+) All tests pass

File size: 6.0 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 sendBuffSize = 0;
83    for (itSend = itbSend; itSend != iteSend; ++itSend) sendBuffSize = (sendBuffSize < itSend->second.numElements())
84                                                                     ? itSend->second.numElements(): sendBuffSize;
85    double* sendBuff;
86    if (0 != sendBuffSize) sendBuff = new double[sendBuffSize];
87    std::vector<MPI_Request> sendRequest;
88    for (itSend = itbSend; itSend != iteSend; ++itSend)
89    {
90      int destRank = itSend->first;
91      const CArray<int,1>& localIndex_p = itSend->second;
92      int countSize = localIndex_p.numElements();
93      for (int idx = 0; idx < countSize; ++idx)
94      {
95        sendBuff[idx] = dataSrc(localIndex_p(idx));
96      }
97      sendRequest.push_back(MPI_Request());
98      MPI_Isend(sendBuff, countSize, MPI_DOUBLE, destRank, 12, client->intraComm, &sendRequest.back());
99    }
100
101    // Receiving data on destination fields
102    std::map<int,std::vector<std::vector<std::pair<int,double> > > >::const_iterator itbRecv = localIndexToReceive.begin(), itRecv,
103                                                                                     iteRecv = localIndexToReceive.end();
104    int recvBuffSize = 0;
105    for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv) recvBuffSize = (recvBuffSize < itRecv->second.size())
106                                                                     ? itRecv->second.size() : recvBuffSize;
107    double* recvBuff;
108    if (0 != recvBuffSize) recvBuff = new double[recvBuffSize];
109    for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
110    {
111      MPI_Status status;
112      int srcRank = itRecv->first;
113      int countSize = itRecv->second.size();
114      MPI_Recv(recvBuff, recvBuffSize, MPI_DOUBLE, srcRank, 12, client->intraComm, &status);
115      for (int idx = 0; idx < countSize; ++idx)
116      {
117        const std::vector<std::pair<int,double> >& localIndex_p = itRecv->second[idx];
118        int numIndex = localIndex_p.size();
119        for (int i = 0; i < numIndex; ++i)
120        {
121//        if (localIndex_p[i].first >= dataDest.numElements())
122          dataDest(localIndex_p[i].first) += recvBuff[idx] * localIndex_p[i].second;
123        }
124      }
125    }
126
127    std::vector<MPI_Status> requestStatus(sendRequest.size());
128    if (!sendRequest.empty()) MPI_Wait(&sendRequest[0], &requestStatus[0]);
129    if (0 != sendBuffSize) delete [] sendBuff;
130    if (0 != recvBuffSize) delete [] recvBuff;
131  }
132} // namespace xios
Note: See TracBrowser for help on using the repository browser.