source: XIOS/trunk/src/transformation/grid_transformation_selector.cpp @ 897

Last change on this file since 897 was 897, checked in by mhnguyen, 8 years ago

Fixing bug in transformation selector

+) If grid source and grid destination are the same (case of special transformations)
we still check transformation list

  • Property svn:executable set to *
File size: 11.7 KB
Line 
1/*!
2   \file grid_transformation.cpp
3   \author Ha NGUYEN
4   \since 14 May 2015
5   \date 02 Jul 2015
6
7   \brief Interface for all transformations.
8 */
9#include "grid_transformation_selector.hpp"
10#include "grid.hpp"
11//#include <boost/unordered_map.hpp>
12
13namespace xios {
14
15CGridTransformationSelector::CGridTransformationSelector(CGrid* destination, CGrid* source, TransformationType type)
16 : gridSource_(source), gridDestination_(destination), isSameGrid_(false),
17  listAlgos_(), algoTypes_(), nbNormalAlgos_(0), nbSpecialAlgos_(0), auxInputs_()
18{
19  if (0 == source)
20  {  gridSource_ = gridDestination_; isSameGrid_ = true; }
21
22  //Verify the compatibity between two grids
23  int numElement = gridDestination_->axis_domain_order.numElements();
24  if (numElement != gridSource_->axis_domain_order.numElements())
25    ERROR("CGridTransformationSelector::CGridTransformationSelector(CGrid* destination, CGrid* source)",
26       << "Two grids have different number of elements"
27       << "Number of elements of grid source " <<gridSource_->getId() << " is " << gridSource_->axis_domain_order.numElements()  << std::endl
28       << "Number of elements of grid destination " <<gridDestination_->getId() << " is " << numElement);
29  initializeTransformations(type);
30}
31
32/*!
33  Initialize the mapping between the first grid source and the original one
34  In a series of transformation, for each step, there is a need to "create" a new grid that plays a role of "temporary" source.
35Because at the end of the series, we need to know about the index mapping between the final grid destination and original grid source,
36for each transformation, we need to make sure that the current "temporary source" maps its global index correctly to the original one.
37*/
38void CGridTransformationSelector::initializeTransformations(TransformationType type)
39{
40  // Initialize algorithms
41  initializeAlgorithms();
42  ListAlgoType::iterator itb = listAlgos_.begin(),
43                         ite = listAlgos_.end(), it;
44
45  for (it = itb; it != ite; ++it)
46  {
47    ETranformationType transType = (it->second).first;
48    if (!isSpecialTransformation(transType))
49    {
50      ++nbNormalAlgos_;
51      if (special == type)
52      {
53        it = listAlgos_.erase(it);
54        --it;
55      }
56    }
57    else
58    {
59      ++nbSpecialAlgos_;
60      if (normal == type)
61      {
62        it = listAlgos_.erase(it);
63        --it;
64      }
65    }
66
67  }
68}
69
70CGridTransformationSelector::~CGridTransformationSelector()
71{
72  std::vector<CGenericAlgorithmTransformation*>::const_iterator itb = algoTransformation_.begin(), it,
73                                                                ite = algoTransformation_.end();
74  for (it = itb; it != ite; ++it) delete (*it);
75}
76
77/*!
78  Initialize the algorithms (transformations)
79*/
80void CGridTransformationSelector::initializeAlgorithms()
81{
82  int idxScalar = 0, idxAxis = 0, idxDomain = 0;
83  CArray<int,1> axisDomainOrderDst = gridDestination_->axis_domain_order;
84  for (int i = 0; i < axisDomainOrderDst.numElements(); ++i)
85  {
86    int dimElement = axisDomainOrderDst(i);
87    if (2 == dimElement)
88    {
89      elementPositionInGridDst2DomainPosition_[i] = idxDomain;
90      ++idxDomain;
91    }
92    else if (1 == dimElement)
93    {
94      elementPositionInGridDst2AxisPosition_[i] = idxAxis;
95      ++idxAxis;
96    }
97    else
98    {
99      elementPositionInGridDst2ScalarPosition_[i] = idxScalar;
100      ++idxScalar;
101    }
102  }
103
104  idxScalar = idxAxis = idxDomain = 0;
105  CArray<int,1> axisDomainOrderSrc = gridSource_->axis_domain_order;
106  for (int i = 0; i < axisDomainOrderSrc.numElements(); ++i)
107  {
108    int dimElement = axisDomainOrderSrc(i);
109    if (2 == dimElement)
110    {
111      elementPositionInGridSrc2DomainPosition_[i] = idxDomain;
112      ++idxDomain;
113    }
114    else if (1 == dimElement)
115    {
116      elementPositionInGridSrc2AxisPosition_[i] = idxAxis;
117      ++idxAxis;
118    }
119    else
120    {
121      elementPositionInGridSrc2ScalarPosition_[i] = idxScalar;
122      ++idxScalar;
123    }
124  }
125
126  for (int i = 0; i < axisDomainOrderDst.numElements(); ++i)
127  {
128    int dimElement = axisDomainOrderDst(i);
129    if (2 == dimElement)
130    {
131      initializeDomainAlgorithms(i);
132    }
133    else if (1 == dimElement)
134    {
135      initializeAxisAlgorithms(i);
136    }
137    else
138    {
139      initializeScalarAlgorithms(i);
140    }
141  }
142}
143
144/*!
145  Initialize the algorithms corresponding to transformation info contained in each scalar.
146If an scalar has transformations, these transformations will be represented in form of vector of CTransformation pointers
147In general, each scalar can have several transformations performed on itself. However, should they be done seperately or combinely (of course in order)?
148For now, one approach is to do these combinely but maybe this needs changing.
149\param [in] axisPositionInGrid position of an axis in grid. (for example: a grid with one domain and one scalar, position of domain is 0, position of axis is 1)
150*/
151void CGridTransformationSelector::initializeScalarAlgorithms(int scalarPositionInGrid)
152{
153  std::vector<CScalar*> scalarListDestP = gridDestination_->getScalars();
154  std::vector<CScalar*> scalarListSrcP = gridSource_->getScalars();
155  if (!scalarListDestP.empty())
156  {
157    int scalarDstPos = -1, scalarSrcPos = -1;
158    if (0 < elementPositionInGridDst2ScalarPosition_.count(scalarPositionInGrid))
159      scalarDstPos = elementPositionInGridDst2AxisPosition_[scalarPositionInGrid];
160    if (0 < elementPositionInGridSrc2ScalarPosition_.count(scalarPositionInGrid))
161      scalarSrcPos = elementPositionInGridSrc2AxisPosition_[scalarPositionInGrid];
162
163    // If source and destination grid share the same scalar
164    if ((-1 != scalarDstPos) && (-1 != scalarSrcPos) &&
165        (scalarListDestP[scalarDstPos] == scalarListSrcP[scalarSrcPos]) && !isSameGrid_) return;
166
167    if (scalarListDestP[scalarDstPos]->hasTransformation())
168    {
169      CScalar::TransMapTypes trans = scalarListDestP[scalarDstPos]->getAllTransformations();
170      CScalar::TransMapTypes::const_iterator itb = trans.begin(), it,
171                                           ite = trans.end();
172      int transformationOrder = 0;
173      for (it = itb; it != ite; ++it)
174      {
175        listAlgos_.push_back(std::make_pair(scalarPositionInGrid, std::make_pair(it->first, transformationOrder)));
176        algoTypes_.push_back(scalarType);
177        ++transformationOrder;
178        std::vector<StdString> auxInput = (it->second)->checkAuxInputs();
179        for (int idx = 0; idx < auxInput.size(); ++idx) auxInputs_.push_back(auxInput[idx]);
180      }
181    }
182  }
183}
184
185/*!
186  Initialize the algorithms corresponding to transformation info contained in each axis.
187If an axis has transformations, these transformations will be represented in form of vector of CTransformation pointers
188In general, each axis can have several transformations performed on itself. However, should they be done seperately or combinely (of course in order)?
189For now, one approach is to do these combinely but maybe this needs changing.
190\param [in] axisPositionInGrid position of an axis in grid. (for example: a grid with one domain and one axis, position of domain is 1, position of axis is 2)
191*/
192void CGridTransformationSelector::initializeAxisAlgorithms(int axisPositionInGrid)
193{
194  std::vector<CAxis*> axisListDestP = gridDestination_->getAxis();
195  std::vector<CAxis*> axisListSrcP = gridSource_->getAxis();
196  if (!axisListDestP.empty())
197  {
198    int axisDstPos = -1, axisSrcPos = -1;
199    if (0 < elementPositionInGridDst2AxisPosition_.count(axisPositionInGrid))
200      axisDstPos = elementPositionInGridDst2AxisPosition_[axisPositionInGrid];
201    if (0 < elementPositionInGridSrc2AxisPosition_.count(axisPositionInGrid))
202      axisSrcPos = elementPositionInGridSrc2AxisPosition_[axisPositionInGrid];
203
204    // If source and destination grid share the same axis
205    if ((-1 != axisDstPos) && (-1 != axisSrcPos) &&
206        (axisListDestP[axisDstPos] == axisListSrcP[axisSrcPos]) && !isSameGrid_) return;
207
208    if (axisListDestP[axisDstPos]->hasTransformation())
209    {
210      CAxis::TransMapTypes trans = axisListDestP[axisDstPos]->getAllTransformations();
211      CAxis::TransMapTypes::const_iterator itb = trans.begin(), it,
212                                           ite = trans.end();
213      int transformationOrder = 0;
214      for (it = itb; it != ite; ++it)
215      {
216        listAlgos_.push_back(std::make_pair(axisPositionInGrid, std::make_pair(it->first, transformationOrder)));
217        algoTypes_.push_back(axisType);
218        ++transformationOrder;
219        std::vector<StdString> auxInput = (it->second)->checkAuxInputs();
220        for (int idx = 0; idx < auxInput.size(); ++idx) auxInputs_.push_back(auxInput[idx]);
221      }
222    }
223  }
224}
225
226/*!
227  Initialize the algorithms corresponding to transformation info contained in each domain.
228If a domain has transformations, they will be represented in form of vector of CTransformation pointers
229In general, each domain can have several transformations performed on itself.
230\param [in] domPositionInGrid position of a domain in grid. (for example: a grid with one domain and one axis, position of domain is 1, position of axis is 2)
231*/
232void CGridTransformationSelector::initializeDomainAlgorithms(int domPositionInGrid)
233{
234  std::vector<CDomain*> domListDestP = gridDestination_->getDomains();
235  std::vector<CDomain*> domListSrcP = gridSource_->getDomains();
236  if (!domListDestP.empty())
237  {
238    int domDstPos = -1, domSrcPos = -1;
239    if (0 < elementPositionInGridDst2DomainPosition_.count(domPositionInGrid))
240      domDstPos = elementPositionInGridDst2AxisPosition_[domPositionInGrid];
241    if (0 < elementPositionInGridSrc2DomainPosition_.count(domPositionInGrid))
242      domSrcPos = elementPositionInGridSrc2AxisPosition_[domPositionInGrid];
243
244    // If source and destination grid share the same domain
245    if ((-1 != domDstPos) && (-1 != domSrcPos) &&
246        (domListDestP[domDstPos] == domListSrcP[domSrcPos]) && !isSameGrid_) return;
247
248    if (domListDestP[domDstPos]->hasTransformation())
249    {
250      CDomain::TransMapTypes trans = domListDestP[domDstPos]->getAllTransformations();
251      CDomain::TransMapTypes::const_iterator itb = trans.begin(), it,
252                                             ite = trans.end();
253      int transformationOrder = 0;
254      for (it = itb; it != ite; ++it)
255      {
256        listAlgos_.push_back(std::make_pair(domPositionInGrid, std::make_pair(it->first, transformationOrder)));
257        algoTypes_.push_back(domainType);
258        ++transformationOrder;
259        std::vector<StdString> auxInput = (it->second)->checkAuxInputs();
260        for (int idx = 0; idx < auxInput.size(); ++idx) auxInputs_.push_back(auxInput[idx]);
261      }
262    }
263  }
264
265}
266
267/*!
268  Select algorithm correspoding to its transformation type and its position in each element
269  \param [in] elementPositionInGrid position of element in grid. e.g: a grid has 1 domain and 1 axis, then position of domain is 1 (because it contains 2 basic elements)
270                                             and position of axis is 2
271  \param [in] transType transformation type, for now we have Zoom_axis, inverse_axis
272  \param [in] transformationOrder position of the transformation in an element (an element can have several transformation)
273  \param [in] isDomainAlgo flag to specify type of algorithm (for domain or axis)
274*/
275void CGridTransformationSelector::selectAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder, AlgoType algoType)
276{
277  switch (algoType)
278  {
279  case scalarType:
280    selectScalarAlgo(elementPositionInGrid, transType, transformationOrder);
281    break;
282  case axisType:
283    selectAxisAlgo(elementPositionInGrid, transType, transformationOrder);
284    break;
285  case domainType:
286    selectDomainAlgo(elementPositionInGrid, transType, transformationOrder);
287    break;
288  default:
289    break;
290  }
291}
292
293bool CGridTransformationSelector::isSpecialTransformation(ETranformationType transType)
294{
295  bool res = false;
296  switch (transType)
297  {
298    case TRANS_GENERATE_RECTILINEAR_DOMAIN:
299     res = true;
300     break;
301    default:
302     break;
303  }
304
305  return res;
306}
307
308}
Note: See TracBrowser for help on using the repository browser.