source: XIOS/dev/branch_openmp/src/transformation/grid_transformation_selector.cpp @ 1460

Last change on this file since 1460 was 1460, checked in by yushan, 6 years ago

branch_openmp merged with XIOS_DEV_CMIP6@1459

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