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

Last change on this file since 650 was 644, checked in by rlacroix, 9 years ago

Use the filter infrastructure to handle the spatial transformations.

Add a spatial transform filter to do so.

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