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

Last change on this file since 933 was 933, checked in by mhnguyen, 4 years ago

Improving transformation selection. Instead of modifying directly grid_transformation
we only need to register a new transformation with the framework

+) Update all transformations with this new method

Test
+) On Curie
+) Basic tests pass

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