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

Last change on this file since 1314 was 1314, checked in by ymipsl, 3 years ago

Add 2 new spatial transformations :

  • reduce_scalar_to_scalar : global reduction between scalar
  • duplicate_scalar_to_axis : a scalar value is duplicated on each level of the axis.

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