source: XIOS/dev/XIOS_DEV_CMIP6/src/transformation/grid_transformation_selector.cpp @ 1620

Last change on this file since 1620 was 1457, checked in by ymipsl, 6 years ago

Add new domain filter : reorder_domain
Reoder the data along the global domain but works only for rectilinear domain

  • invert_lat : invert the latitute axis
  • shift_lon_fraction : shift the longitude axis of a fration of global size
  • lon_min/lon_max : fixe the range of longitude value (ex : -180:180 or 0:360)

YM

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