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

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

implement diurnal cycle transformation taken as a grid tranformation : scalar -> axis

YM

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