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

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

Add new transformation : reduce axis_to_axis
This a global reduction implying all process whih own the same source axis global point.

YM

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