source: XIOS/trunk/src/node/grid.cpp @ 620

Last change on this file since 620 was 620, checked in by mhnguyen, 9 years ago

Implementing generic transformation algorithm (local commit)

+) Implement 3 important classes:

-gridTransformation to read transformation info from grid and interface with the rest of XIOS
-transformationMapping to be in charge of sending/receiving transformation info among clients
-transformationAlgorithm to represent various algorithms

+) Make some change on field to use the new classes

Test
+) Only test_new_features with inversed axis

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 40.9 KB
Line 
1
2#include "grid.hpp"
3
4#include "attribute_template.hpp"
5#include "object_template.hpp"
6#include "group_template.hpp"
7#include "message.hpp"
8#include <iostream>
9#include "xios_spl.hpp"
10#include "type.hpp"
11#include "context.hpp"
12#include "context_client.hpp"
13#include "context_server.hpp"
14#include "array_new.hpp"
15#include "client_server_mapping_distributed.hpp"
16
17namespace xios {
18
19   /// ////////////////////// Définitions ////////////////////// ///
20
21   CGrid::CGrid(void)
22      : CObjectTemplate<CGrid>(), CGridAttributes()
23      , isChecked(false), isDomainAxisChecked(false), storeIndex(1)
24      , vDomainGroup_(), vAxisGroup_(), axisList_(), isAxisListSet(false), isDomListSet(false), clientDistribution_(0), isIndexSent(false)
25      , serverDistribution_(0), serverDistributionDescription_(0), clientServerMap_(0), writtenDataSize_(0), globalDim_()
26      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), transformations_(0), isTransformed_(false)
27      , axisPositionInGrid_()
28   {
29     setVirtualDomainGroup();
30     setVirtualAxisGroup();
31   }
32
33   CGrid::CGrid(const StdString & id)
34      : CObjectTemplate<CGrid>(id), CGridAttributes()
35      , isChecked(false), isDomainAxisChecked(false), storeIndex(1)
36      , vDomainGroup_(), vAxisGroup_(), axisList_(), isAxisListSet(false), isDomListSet(false), clientDistribution_(0), isIndexSent(false)
37      , serverDistribution_(0), serverDistributionDescription_(0), clientServerMap_(0), writtenDataSize_(0), globalDim_()
38      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), transformations_(0), isTransformed_(false)
39      , axisPositionInGrid_()
40   {
41     setVirtualDomainGroup();
42     setVirtualAxisGroup();
43   }
44
45   CGrid::~CGrid(void)
46   {
47    deque< CArray<int, 1>* >::iterator it ;
48
49    for(deque< CArray<int,1>* >::iterator it=storeIndex.begin(); it!=storeIndex.end();it++)  delete *it ;
50    for(map<int,CArray<size_t,1>* >::iterator it=outIndexFromClient.begin();it!=outIndexFromClient.end();++it) delete (it->second);
51
52    if (0 != clientDistribution_) delete clientDistribution_;
53    if (0 != serverDistribution_) delete serverDistribution_;
54    if (0 != serverDistributionDescription_) delete serverDistributionDescription_;
55    if (0 != transformations_) delete transformations_;
56   }
57
58   ///---------------------------------------------------------------
59
60   StdString CGrid::GetName(void)    { return (StdString("grid")); }
61   StdString CGrid::GetDefName(void) { return (CGrid::GetName()); }
62   ENodeType CGrid::GetType(void)    { return (eGrid); }
63
64   //----------------------------------------------------------------
65
66   const std::deque< CArray<int,1>* > & CGrid::getStoreIndex(void) const
67   {
68      return (this->storeIndex );
69   }
70
71   //---------------------------------------------------------------
72//
73//   const std::deque< CArray<int,1>* > & CGrid::getOutIIndex(void)  const
74//   {
75//      return (this->out_i_index );
76//   }
77//
78//   //---------------------------------------------------------------
79//
80//   const std::deque< CArray<int,1>* > & CGrid::getOutJIndex(void)  const
81//   {
82//      return (this->out_j_index );
83//   }
84//
85//   //---------------------------------------------------------------
86//
87//   const std::deque< CArray<int,1>* > & CGrid::getOutLIndex(void)  const
88//   {
89//      return (this->out_l_index );
90//   }
91//
92//   //---------------------------------------------------------------
93//
94//   const CAxis*   CGrid::getRelAxis  (void) const
95//   {
96//      return (this->axis );
97//   }
98
99//   //---------------------------------------------------------------
100//
101//   const CDomain* CGrid::getRelDomain(void) const
102//   {
103//      return (this->domain );
104//   }
105
106   //---------------------------------------------------------------
107
108//   bool CGrid::hasAxis(void) const
109//   {
110//      return (this->withAxis);
111//   }
112
113   //---------------------------------------------------------------
114
115   StdSize CGrid::getDimension(void) const
116   {
117      return (globalDim_.size());
118   }
119
120   //---------------------------------------------------------------
121
122/*
123   std::vector<StdSize> CGrid::getLocalShape(void) const
124   {
125      std::vector<StdSize> retvalue;
126      retvalue.push_back(domain->zoom_ni_loc.getValue());
127      retvalue.push_back(domain->zoom_nj_loc.getValue());
128      if (this->withAxis)
129         retvalue.push_back(this->axis->zoom_size.getValue());
130      return (retvalue);
131   }
132*/
133   //---------------------------------------------------------------
134
135/*
136   StdSize CGrid::getLocalSize(void) const
137   {
138      StdSize retvalue = 1;
139      std::vector<StdSize> shape_ = this->getLocalShape();
140      for (StdSize s = 0; s < shape_.size(); s++)
141         retvalue *= shape_[s];
142      return (retvalue);
143   }
144*/
145   //---------------------------------------------------------------
146/*
147   std::vector<StdSize> CGrid::getGlobalShape(void) const
148   {
149      std::vector<StdSize> retvalue;
150      retvalue.push_back(domain->ni.getValue());
151      retvalue.push_back(domain->nj.getValue());
152      if (this->withAxis)
153         retvalue.push_back(this->axis->size.getValue());
154      return (retvalue);
155   }
156*/
157   //---------------------------------------------------------------
158
159/*
160   StdSize CGrid::getGlobalSize(void) const
161   {
162      StdSize retvalue = 1;
163      std::vector<StdSize> shape_ = this->getGlobalShape();
164      for (StdSize s = 0; s < shape_.size(); s++)
165         retvalue *= shape_[s];
166      return (retvalue);
167   }
168*/
169   StdSize CGrid::getDataSize(void) const
170   {
171     StdSize retvalue = 1;
172     if (!isScalarGrid())
173     {
174       std::vector<int> dataNindex = clientDistribution_->getDataNIndex();
175       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];
176     }
177     return retvalue;
178   }
179
180   std::map<int, StdSize> CGrid::getConnectedServerDataSize()
181   {
182     double secureFactor = 2.5 * sizeof(double) * CXios::bufferServerFactorSize;
183     StdSize retVal = 1;
184     std::map<int, StdSize> ret;
185     std::map<int, size_t >::const_iterator itb = connectedDataSize_.begin(), it, itE = connectedDataSize_.end();
186
187     if (isScalarGrid())
188     {
189       for (it = itb; it != itE; ++it)
190       {
191         retVal *= secureFactor;
192         ret.insert(std::make_pair(it->first, retVal));
193       }
194       return ret;
195     }
196
197     for (it = itb; it != itE; ++it)
198     {
199        retVal = it->second;
200        retVal *= secureFactor;
201        ret.insert(std::make_pair<int,StdSize>(it->first, retVal));
202     }
203
204     if (connectedDataSize_.empty())
205     {
206       for (int i = 0; i < connectedServerRank_.size(); ++i)
207       {
208         retVal = 1;
209         retVal *= secureFactor;
210         ret.insert(std::make_pair<int,StdSize>(connectedServerRank_[i], retVal));
211       }
212     }
213
214     return ret;
215   }
216
217
218   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
219   {
220     if (this->isDomainAxisChecked) return;
221
222     this->solveAxisRef(areAttributesChecked);
223     this->solveDomainRef(areAttributesChecked);
224
225     this->isDomainAxisChecked = areAttributesChecked;
226   }
227
228   void CGrid::checkMaskIndex(bool doSendingIndex)
229   {
230     CContext* context = CContext::getCurrent() ;
231     CContextClient* client=context->client ;
232
233     if (isScalarGrid())
234     {
235       if (context->hasClient)
236          if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndexScalarGrid(); this->isIndexSent = true; }
237
238       if (this->isChecked) return;
239       if (context->hasClient)
240       {
241          this->computeIndexScalarGrid();
242       }
243
244       this->isChecked = true;
245       return;
246     }
247
248     if (context->hasClient)
249      if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndex(); this->isIndexSent = true; }
250
251     if (this->isChecked) return;
252
253     if (context->hasClient)
254     {
255        checkMask() ;
256        this->computeIndex() ;
257        this->storeIndex.push_front(new CArray<int,1>() );
258     }
259     this->isChecked = true;
260   }
261
262   void CGrid::checkMask(void)
263   {
264      using namespace std;
265      std::vector<CDomain*> domainP = this->getDomains();
266      std::vector<CAxis*> axisP = this->getAxis();
267      int dim = domainP.size() * 2 + axisP.size();
268
269      std::vector<CArray<bool,2>* > domainMasks(domainP.size());
270      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask);
271      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
272      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
273
274      switch (dim) {
275        case 1:
276          checkGridMask(mask1, domainMasks, axisMasks, axis_domain_order);
277          break;
278        case 2:
279          checkGridMask(mask2, domainMasks, axisMasks, axis_domain_order);
280          break;
281        case 3:
282          checkGridMask(mask3, domainMasks, axisMasks, axis_domain_order);
283          break;
284//        case 4:
285//          checkGridMask(mask4, domainMasks, axisMasks, axis_domain_order);
286//          break;
287//        case 5:
288//          checkGridMask(mask5, domainMasks, axisMasks, axis_domain_order);
289//          break;
290//        case 6:
291//          checkGridMask(mask6, domainMasks, axisMasks, axis_domain_order);
292//          break;
293//        case 7:
294//          checkGridMask(mask7, domainMasks, axisMasks, axis_domain_order);
295//          break;
296        default:
297          break;
298      }
299   }
300   //---------------------------------------------------------------
301
302   void CGrid::solveDomainRef(bool sendAtt)
303   {
304      setDomainList();
305      std::vector<CDomain*> domListP = this->getDomains();
306      if (!domListP.empty())
307      {
308        computeGridGlobalDimension(getDomains(), getAxis(), axis_domain_order);
309        for (int i = 0; i < domListP.size(); ++i)
310        {
311          if (sendAtt) domListP[i]->sendCheckedAttributes();
312          else domListP[i]->checkAttributesOnClient();
313        }
314      }
315   }
316
317   //---------------------------------------------------------------
318
319   void CGrid::solveAxisRef(bool sendAtt)
320   {
321      setAxisList();
322      std::vector<CAxis*> axisListP = this->getAxis();
323      if (!axisListP.empty())
324      {
325        int idx = 0;
326        axisPositionInGrid_.resize(0);
327        for (int i = 0; i < axis_domain_order.numElements(); ++i)
328        {
329          if (false == axis_domain_order(i))
330          {
331            axisPositionInGrid_.push_back(idx);
332            ++idx;
333          }
334          else idx += 2;
335        }
336
337        computeGridGlobalDimension(getDomains(), getAxis(), axis_domain_order);
338        for (int i = 0; i < axisListP.size(); ++i)
339        {
340          if (sendAtt)
341            axisListP[i]->sendCheckedAttributes(globalDim_,axisPositionInGrid_[i]);
342          else
343            axisListP[i]->checkAttributesOnClient(globalDim_,axisPositionInGrid_[i]);
344          ++idx;
345        }
346
347      }
348   }
349
350   std::vector<int> CGrid::getAxisPositionInGrid() const
351   {
352     return axisPositionInGrid_;
353   }
354
355
356   //---------------------------------------------------------------
357
358   void CGrid::computeIndex(void)
359   {
360     CContext* context = CContext::getCurrent() ;
361     CContextClient* client=context->client ;
362
363     // First of all, compute distribution on client side
364     clientDistribution_ = new CDistributionClient(client->clientRank, this);
365     // Get local data index on client
366     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().numElements());
367     storeIndex_client = (clientDistribution_->getLocalDataIndexOnClient());
368     isDataDistributed_= clientDistribution_->isDataDistributed();
369
370     if (!doGridHaveDataDistributed())
371     {
372        if (0 == client->clientRank)
373        {
374          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().numElements();
375          for (int rank = 0; rank < client->serverSize; ++rank)
376            connectedDataSize_[rank] = ssize;
377        }
378        return;
379     }
380
381     // Compute mapping between client and server
382     size_t globalSizeIndex = 1, indexBegin, indexEnd;
383     int range, clientSize = client->clientSize;
384     for (int i = 0; i < globalDim_.size(); ++i) globalSizeIndex *= globalDim_[i];
385     indexBegin = 0;
386     for (int i = 0; i < clientSize; ++i)
387     {
388       range = globalSizeIndex / clientSize;
389       if (i < (globalSizeIndex%clientSize)) ++range;
390       if (i == client->clientRank) break;
391       indexBegin += range;
392     }
393     indexEnd = indexBegin + range - 1;
394
395     // Then compute distribution on server side
396     serverDistributionDescription_ = new CServerDistributionDescription(clientDistribution_->getNGlob());
397     serverDistributionDescription_->computeServerDistribution(client->serverSize, true);
398     serverDistributionDescription_->computeServerGlobalIndexInRange(client->serverSize,
399                                                                     std::make_pair<size_t,size_t>(indexBegin, indexEnd));
400
401     // Finally, compute index mapping between client(s) and server(s)
402     clientServerMap_ = new CClientServerMappingDistributed(serverDistributionDescription_->getGlobalIndexRange(),
403                                                            client->intraComm,
404                                                            clientDistribution_->isDataDistributed());
405
406     clientServerMap_->computeServerIndexMapping(clientDistribution_->getGlobalIndex());
407     const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
408     const CArray<size_t,1>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
409
410     std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
411     itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
412     iteGlobalMap = globalIndexOnServer.end();
413
414     int nbGlobalIndex = globalIndexSendToServer.numElements();
415    for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
416    {
417      int serverRank = itGlobalMap->first;
418      std::vector<size_t>::const_iterator itbVecGlobal = (itGlobalMap->second).begin(), itVecGlobal,
419                                          iteVecGlobal = (itGlobalMap->second).end();
420      for (int i = 0; i < nbGlobalIndex; ++i)
421      {
422        if (iteVecGlobal != std::find(itbVecGlobal, iteVecGlobal, globalIndexSendToServer(i)))
423        {
424          if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
425            connectedDataSize_[serverRank] = 1;
426          else
427            ++connectedDataSize_[serverRank];
428        }
429      }
430    }
431
432   connectedServerRank_.clear();
433   for (std::map<int, std::vector<size_t> >::const_iterator it = globalIndexOnServer.begin(); it != globalIndexOnServer.end(); ++it) {
434     connectedServerRank_.push_back(it->first);
435   }
436   if (!connectedDataSize_.empty())
437   {
438     connectedServerRank_.clear();
439     for (std::map<int,size_t>::const_iterator it = connectedDataSize_.begin(); it != connectedDataSize_.end(); ++it)
440       connectedServerRank_.push_back(it->first);
441   }
442
443    nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
444   }
445
446   //----------------------------------------------------------------
447
448   CGrid* CGrid::createGrid(CDomain* domain)
449   {
450      std::vector<CDomain*> vecDom(1,domain);
451      std::vector<CAxis*> vecAxis;
452
453      CGrid* grid = createGrid(vecDom, vecAxis);
454
455      return (grid);
456   }
457
458   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
459   {
460      std::vector<CDomain*> vecDom(1,domain);
461      std::vector<CAxis*> vecAxis(1,axis);
462      CGrid* grid = createGrid(vecDom, vecAxis);
463
464      return (grid);
465   }
466
467   CGrid* CGrid::createGrid(std::vector<CDomain*> domains, std::vector<CAxis*> axis)
468   {
469      StdString new_id = StdString("__");
470      if (!domains.empty()) for (int i = 0; i < domains.size(); ++i) new_id += domains[i]->getId() + StdString("_");
471      if (!axis.empty()) for (int i = 0; i < axis.size(); ++i) new_id += axis[i]->getId() + StdString("_") ;
472      if (domains.empty() && axis.empty()) new_id += StdString("scalar_grid");
473      new_id += StdString("_");
474
475      CGrid* grid = CGridGroup::get("grid_definition")->createChild(new_id) ;
476      grid->setDomainList(domains);
477      grid->setAxisList(axis);
478
479      //By default, domains are always the first ones of a grid
480      if (grid->axis_domain_order.isEmpty())
481      {
482        int size = domains.size()+axis.size();
483        grid->axis_domain_order.resize(size);
484        for (int i = 0; i < size; ++i)
485        {
486          if (i < domains.size()) grid->axis_domain_order(i) = true;
487          else grid->axis_domain_order(i) = false;
488        }
489      }
490
491      grid->computeGridGlobalDimension(domains, axis, grid->axis_domain_order);
492
493      return (grid);
494   }
495
496   CDomainGroup* CGrid::getVirtualDomainGroup() const
497   {
498     return (this->vDomainGroup_);
499   }
500
501   CAxisGroup* CGrid::getVirtualAxisGroup() const
502   {
503     return (this->vAxisGroup_);
504   }
505
506   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
507   {
508     CArray<size_t,1>& out_i=*outIndexFromClient[rank];
509     StdSize numElements = stored.numElements();
510     for (StdSize n = 0; n < numElements; ++n)
511     {
512       *(field+out_i(n)) = stored(n);
513     }
514   }
515
516   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
517   {
518     CArray<size_t,1>& out_i = *outIndexFromClient[rank];
519     StdSize numElements = stored.numElements();
520     for (StdSize n = 0; n < numElements; ++n)
521     {
522       stored(n) = *(field+out_i(n));
523     }
524   }
525
526   //----------------------------------------------------------------
527
528
529   void CGrid::storeField_arr
530      (const double * const data, CArray<double, 1>& stored) const
531   {
532      const StdSize size = storeIndex_client.numElements() ;
533
534      stored.resize(size) ;
535      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)] ;
536   }
537
538   void CGrid::restoreField_arr
539      (const CArray<double, 1>& stored, double * const data) const
540   {
541      const StdSize size = storeIndex_client.numElements() ;
542
543      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i) ;
544   }
545
546  void CGrid::computeIndexScalarGrid()
547  {
548    CContext* context = CContext::getCurrent();
549    CContextClient* client=context->client;
550
551    storeIndex_client.resize(1);
552    storeIndex_client[0] = 0;
553    if (0 == client->clientRank)
554    {
555      for (int rank = 0; rank < client->serverSize; ++rank)
556        connectedDataSize_[rank] = 1;
557    }
558    isDataDistributed_ = false;
559  }
560
561  void CGrid::sendIndexScalarGrid()
562  {
563    CContext* context = CContext::getCurrent() ;
564    CContextClient* client=context->client ;
565
566    CEventClient event(getType(),EVENT_ID_INDEX);
567    list<shared_ptr<CMessage> > list_msg ;
568    list< CArray<size_t,1>* > listOutIndex;
569    if (0 == client->clientRank)
570    {
571      for (int rank = 0; rank < client->serverSize; ++rank)
572      {
573        int nb = 1;
574        CArray<size_t, 1> outGlobalIndexOnServer(nb);
575        CArray<int, 1> outLocalIndexToServer(nb);
576        for (int k = 0; k < nb; ++k)
577        {
578          outGlobalIndexOnServer(k) = 0;
579          outLocalIndexToServer(k)  = 0;
580        }
581
582        storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer) ));
583        listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
584
585        list_msg.push_back(shared_ptr<CMessage>(new CMessage));
586        *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
587
588        event.push(rank, 1, *list_msg.back());
589      }
590      client->sendEvent(event);
591    }
592    else
593      client->sendEvent(event);
594
595    for(list<CArray<size_t,1>* >::iterator it=listOutIndex.begin();it!=listOutIndex.end();++it) delete *it ;
596  }
597
598  void CGrid::sendIndex(void)
599  {
600    CContext* context = CContext::getCurrent() ;
601    CContextClient* client=context->client ;
602
603    CEventClient event(getType(),EVENT_ID_INDEX) ;
604    int rank ;
605    list<shared_ptr<CMessage> > list_msg ;
606    list< CArray<size_t,1>* > listOutIndex;
607    const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
608    const CArray<int,1>& localIndexSendToServer = clientDistribution_->getLocalDataIndexSendToServer();
609    const CArray<size_t,1>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
610
611    if (!doGridHaveDataDistributed())
612    {
613      if (0 == client->clientRank)
614      {
615        CArray<size_t, 1> outGlobalIndexOnServer = globalIndexSendToServer;
616        CArray<int,1> outLocalIndexToServer = localIndexSendToServer;
617        for (rank = 0; rank < client->serverSize; ++rank)
618        {
619          storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer)));
620          listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
621
622          list_msg.push_back(shared_ptr<CMessage>(new CMessage));
623          *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
624
625          event.push(rank, 1, *list_msg.back());
626        }
627        client->sendEvent(event);
628      }
629      else
630        client->sendEvent(event);
631    }
632    else
633    {
634      std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
635      itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
636      iteGlobalMap = globalIndexOnServer.end();
637
638      int nbGlobalIndex = globalIndexSendToServer.numElements();
639      std::map<int,std::vector<int> >localIndexTmp;
640      std::map<int,std::vector<size_t> > globalIndexTmp;
641      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
642      {
643        int serverRank = itGlobalMap->first;
644        std::vector<size_t>::const_iterator itbVecGlobal = (itGlobalMap->second).begin(),
645                                            iteVecGlobal = (itGlobalMap->second).end();
646        for (int i = 0; i < nbGlobalIndex; ++i)
647        {
648          if (iteVecGlobal != std::find(itbVecGlobal, iteVecGlobal, globalIndexSendToServer(i)))
649          {
650            globalIndexTmp[serverRank].push_back(globalIndexSendToServer(i));
651            localIndexTmp[serverRank].push_back(localIndexSendToServer(i));
652          }
653        }
654      }
655
656      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
657      {
658        rank = connectedServerRank_[ns];
659        int nb = 0;
660        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
661          nb = globalIndexTmp[rank].size();
662
663        CArray<size_t, 1> outGlobalIndexOnServer(nb);
664        CArray<int, 1> outLocalIndexToServer(nb);
665        for (int k = 0; k < nb; ++k)
666        {
667          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
668          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
669        }
670
671        storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer) ));
672        listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
673
674        list_msg.push_back(shared_ptr<CMessage>(new CMessage));
675        *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
676
677        event.push(rank, nbSenders[rank], *list_msg.back());
678      }
679
680      client->sendEvent(event);
681    }
682
683    for(list<CArray<size_t,1>* >::iterator it=listOutIndex.begin();it!=listOutIndex.end();++it) delete *it ;
684  }
685
686  void CGrid::recvIndex(CEventServer& event)
687  {
688    string gridId;
689    vector<int> ranks;
690    vector<CBufferIn*> buffers;
691
692    list<CEventServer::SSubEvent>::iterator it;
693    for (it=event.subEvents.begin();it!=event.subEvents.end();++it)
694    {
695      ranks.push_back(it->rank);
696      CBufferIn* buffer = it->buffer;
697      *buffer >> gridId;
698      buffers.push_back(buffer);
699    }
700    get(gridId)->recvIndex(ranks, buffers) ;
701  }
702
703  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
704                                         const std::vector<CAxis*>& axis,
705                                         const CArray<bool,1>& axisDomainOrder)
706  {
707    globalDim_.resize(domains.size()*2+axis.size());
708    int idx = 0, idxDomain = 0, idxAxis = 0;
709    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
710    {
711      if (axisDomainOrder(i))
712      {
713        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
714        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
715        ++idxDomain;
716        idx += 2;
717      }
718      else
719      {
720        globalDim_[idx] = axis[idxAxis]->size.getValue();
721        ++idxAxis;
722        ++idx;
723      }
724    }
725  }
726
727  std::vector<int> CGrid::getGlobalDimension()
728  {
729    return globalDim_;
730  }
731
732  bool CGrid::isScalarGrid() const
733  {
734    return (axisList_.empty() && domList_.empty());
735  }
736
737  /*!
738    Verify whether one server need to write data
739    There are some cases on which one server has nodata to write. For example, when we
740  just only want to zoom on a domain.
741  */
742  bool CGrid::doGridHaveDataToWrite()
743  {
744    size_t ssize = 0;
745    for (map<int, CArray<size_t, 1>* >::const_iterator it = outIndexFromClient.begin();
746                                                       it != outIndexFromClient.end(); ++it)
747    {
748      ssize += (it->second)->numElements();
749    }
750    return (0 != ssize);
751  }
752
753  /*!
754    Return size of data which is written on each server
755    Whatever dimension of a grid, data which are written on server must be presented as
756  an one dimension array.
757  \return size of data written on server
758  */
759  size_t CGrid::getWrittenDataSize() const
760  {
761    return writtenDataSize_;
762  }
763
764  const CDistributionServer* CGrid::getDistributionServer() const
765  {
766    return serverDistribution_;
767  }
768
769  const CDistributionClient* CGrid::getDistributionClient() const
770  {
771    return clientDistribution_;
772  }
773
774  bool CGrid::doGridHaveDataDistributed()
775  {
776    if (isScalarGrid()) return false;
777    else
778      return isDataDistributed_;
779  }
780
781  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
782  {
783    CContext* context = CContext::getCurrent();
784    CContextServer* server = context->server;
785
786    for (int n = 0; n < ranks.size(); n++)
787    {
788      int rank = ranks[n];
789      CBufferIn& buffer = *buffers[n];
790
791      buffer >> isDataDistributed_;
792      size_t dataSize = 0;
793
794      if (isScalarGrid())
795      {
796        writtenDataSize_ = 1;
797        CArray<size_t,1> outIndex;
798        buffer >> outIndex;
799        outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
800        std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
801        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
802                                                      nZoomBeginGlobal, nGlob);
803        return;
804      }
805
806      if (0 == serverDistribution_)
807      {
808        int idx = 0, numElement = axis_domain_order.numElements();
809        int ssize = numElement;
810        std::vector<int> indexMap(numElement);
811        for (int i = 0; i < numElement; ++i)
812        {
813          indexMap[i] = idx;
814          if (true == axis_domain_order(i))
815          {
816            ++ssize;
817            idx += 2;
818          }
819          else
820            ++idx;
821        }
822
823        int axisId = 0, domainId = 0;
824        std::vector<CDomain*> domainList = getDomains();
825        std::vector<CAxis*> axisList = getAxis();
826        std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
827        for (int i = 0; i < numElement; ++i)
828        {
829          if (axis_domain_order(i))
830          {
831            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
832            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
833            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->zoom_ibegin;
834            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
835
836            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
837            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
838            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin;
839            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
840            ++domainId;
841          }
842          else
843          {
844            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
845            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
846            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->zoom_begin;
847            nGlob[indexMap[i]] = axisList[axisId]->size;
848            ++axisId;
849          }
850        }
851        dataSize = 1;
852        for (int i = 0; i < nZoomSize.size(); ++i)
853          dataSize *= nZoomSize[i];
854
855        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
856                                                      nZoomBeginGlobal, nGlob);
857      }
858
859      CArray<size_t,1> outIndex;
860      buffer >> outIndex;
861      if (isDataDistributed_)
862        serverDistribution_->computeLocalIndex(outIndex);
863      else
864      {
865        dataSize = outIndex.numElements();
866        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
867      }
868      writtenDataSize_ += dataSize;
869
870      outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
871      connectedDataSize_[rank] = outIndex.numElements();
872    }
873
874    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
875  }
876
877   /*!
878   \brief Dispatch event received from client
879      Whenever a message is received in buffer of server, it will be processed depending on
880   its event type. A new event type should be added in the switch list to make sure
881   it processed on server side.
882   \param [in] event: Received message
883   */
884  bool CGrid::dispatchEvent(CEventServer& event)
885  {
886
887    if (SuperClass::dispatchEvent(event)) return true ;
888    else
889    {
890      switch(event.type)
891      {
892        case EVENT_ID_INDEX :
893          recvIndex(event) ;
894          return true ;
895          break ;
896
897         case EVENT_ID_ADD_DOMAIN :
898           recvAddDomain(event) ;
899           return true ;
900           break ;
901
902         case EVENT_ID_ADD_AXIS :
903           recvAddAxis(event) ;
904           return true ;
905           break ;
906        default :
907          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
908                <<"Unknown Event") ;
909          return false ;
910      }
911    }
912  }
913
914   void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const
915   {
916      if ((this->storeIndex.size()-1 ) != storedClient.size())
917         ERROR("void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const",
918                << "[ Expected received field = " << (this->storeIndex.size()-1) << ", "
919                << "[ received fiedl = "    << storedClient.size() << "] "
920                << "Data from clients are missing!") ;
921      storedServer.resize(storeIndex[0]->numElements());
922
923      for (StdSize i = 0, n = 0; i < storedClient.size(); i++)
924         for (StdSize j = 0; j < storedClient[i]->numElements(); j++)
925            storedServer(n++) = (*storedClient[i])(j);
926   }
927
928   void CGrid::outputFieldToServer(CArray<double,1>& fieldIn, int rank, CArray<double,1>& fieldOut)
929   {
930     CArray<int,1>& index = *storeIndex_toSrv[rank] ;
931     int nb=index.numElements() ;
932     fieldOut.resize(nb) ;
933
934     for(int k=0;k<nb;k++) fieldOut(k)=fieldIn(index(k)) ;
935    }
936   ///---------------------------------------------------------------
937
938   CDomain* CGrid::addDomain(const std::string& id)
939   {
940     return vDomainGroup_->createChild(id) ;
941   }
942
943   CAxis* CGrid::addAxis(const std::string& id)
944   {
945     return vAxisGroup_->createChild(id) ;
946   }
947
948   //! Change virtual field group to a new one
949   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
950   {
951      this->vDomainGroup_ = newVDomainGroup;
952   }
953
954   //! Change virtual variable group to new one
955   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
956   {
957      this->vAxisGroup_ = newVAxisGroup;
958   }
959
960   //----------------------------------------------------------------
961   //! Create virtual field group, which is done normally on initializing file
962   void CGrid::setVirtualDomainGroup(void)
963   {
964      this->setVirtualDomainGroup(CDomainGroup::create());
965   }
966
967   //! Create virtual variable group, which is done normally on initializing file
968   void CGrid::setVirtualAxisGroup(void)
969   {
970      this->setVirtualAxisGroup(CAxisGroup::create());
971   }
972
973   /*!
974   \brief Send a message to create a domain on server side
975   \param[in] id String identity of domain that will be created on server
976   */
977   void CGrid::sendAddDomain(const string& id)
978   {
979    CContext* context=CContext::getCurrent() ;
980
981    if (! context->hasServer )
982    {
983       CContextClient* client=context->client ;
984
985       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN) ;
986       if (client->isServerLeader())
987       {
988         CMessage msg ;
989         msg<<this->getId() ;
990         msg<<id ;
991         const std::list<int>& ranks = client->getRanksServerLeader();
992         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
993           event.push(*itRank,1,msg);
994         client->sendEvent(event) ;
995       }
996       else client->sendEvent(event) ;
997    }
998   }
999
1000   /*!
1001   \brief Send a message to create an axis on server side
1002   \param[in] id String identity of axis that will be created on server
1003   */
1004   void CGrid::sendAddAxis(const string& id)
1005   {
1006    CContext* context=CContext::getCurrent() ;
1007
1008    if (! context->hasServer )
1009    {
1010       CContextClient* client=context->client ;
1011
1012       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS) ;
1013       if (client->isServerLeader())
1014       {
1015         CMessage msg ;
1016         msg<<this->getId() ;
1017         msg<<id ;
1018         const std::list<int>& ranks = client->getRanksServerLeader();
1019         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1020           event.push(*itRank,1,msg);
1021         client->sendEvent(event) ;
1022       }
1023       else client->sendEvent(event) ;
1024    }
1025   }
1026
1027   /*!
1028   \brief Receive a message annoucing the creation of a domain on server side
1029   \param[in] event Received event
1030   */
1031   void CGrid::recvAddDomain(CEventServer& event)
1032   {
1033
1034      CBufferIn* buffer=event.subEvents.begin()->buffer;
1035      string id;
1036      *buffer>>id ;
1037      get(id)->recvAddDomain(*buffer) ;
1038   }
1039
1040   /*!
1041   \brief Receive a message annoucing the creation of a domain on server side
1042   \param[in] buffer Buffer containing message
1043   */
1044   void CGrid::recvAddDomain(CBufferIn& buffer)
1045   {
1046      string id ;
1047      buffer>>id ;
1048      addDomain(id) ;
1049   }
1050
1051   /*!
1052   \brief Receive a message annoucing the creation of an axis on server side
1053   \param[in] event Received event
1054   */
1055   void CGrid::recvAddAxis(CEventServer& event)
1056   {
1057
1058      CBufferIn* buffer=event.subEvents.begin()->buffer;
1059      string id;
1060      *buffer>>id ;
1061      get(id)->recvAddAxis(*buffer) ;
1062   }
1063
1064   /*!
1065   \brief Receive a message annoucing the creation of an axis on server side
1066   \param[in] buffer Buffer containing message
1067   */
1068   void CGrid::recvAddAxis(CBufferIn& buffer)
1069   {
1070      string id ;
1071      buffer>>id ;
1072      addAxis(id) ;
1073   }
1074
1075  /*!
1076  \brief Solve domain and axis references
1077  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1078  all attributes from their parents, they should be processed with this function
1079  \param[in] apply inherit all attributes of parents (true)
1080  */
1081  void CGrid::solveDomainAxisRefInheritance(bool apply)
1082  {
1083    CContext* context = CContext::getCurrent();
1084    unsigned int vecSize, i;
1085    std::vector<StdString>::iterator it, itE;
1086    setDomainList();
1087    it = domList_.begin(); itE = domList_.end();
1088    for (; it != itE; ++it)
1089    {
1090      CDomain* pDom = CDomain::get(*it);
1091      if (context->hasClient)
1092      {
1093        pDom->solveRefInheritance(apply);
1094        pDom->solveBaseReference();
1095        if ((!pDom->domain_ref.isEmpty()) && (pDom->name.isEmpty()))
1096          pDom->name.setValue(pDom->getBaseDomainReference()->getId());
1097      }
1098    }
1099
1100    setAxisList();
1101    it = axisList_.begin(); itE = axisList_.end();
1102    for (; it != itE; ++it)
1103    {
1104      CAxis* pAxis = CAxis::get(*it);
1105      if (context->hasClient)
1106      {
1107        pAxis->solveRefInheritance(apply);
1108        pAxis->solveBaseReference();
1109        pAxis->solveInheritanceTransformation();
1110        if ((!pAxis->axis_ref.isEmpty()) && (pAxis->name.isEmpty()))
1111          pAxis->name.setValue(pAxis->getBaseAxisReference()->getId());
1112      }
1113    }
1114  }
1115
1116  bool CGrid::isTransformed()
1117  {
1118    return isTransformed_;
1119  }
1120
1121  void CGrid::setTransformed()
1122  {
1123    isTransformed_ = true;
1124  }
1125
1126  CGridTransformation* CGrid::getTransformations()
1127  {
1128    return transformations_;
1129  }
1130
1131  void CGrid::transformGrid(CGrid* transformedGrid)
1132  {
1133    if (transformedGrid->isTransformed()) return;
1134    transformedGrid->setTransformed();
1135    if (axis_domain_order.numElements() != transformedGrid->axis_domain_order.numElements())
1136    {
1137      ERROR("CGrid::transformGrid(CGrid* transformedGrid)",
1138           << "Two grids have different dimension size"
1139           << "Dimension of grid source " <<this->getId() << " is " << axis_domain_order.numElements() << std::endl
1140           << "Dimension of grid destination " <<transformedGrid->getId() << " is " << transformedGrid->axis_domain_order.numElements());
1141    }
1142    else
1143    {
1144      int ssize = axis_domain_order.numElements();
1145      for (int i = 0; i < ssize; ++i)
1146        if (axis_domain_order(i) != (transformedGrid->axis_domain_order)(i))
1147          ERROR("CGrid::transformGrid(CGrid* transformedGrid)",
1148                << "Grids " <<this->getId() <<" and " << transformedGrid->getId()
1149                << " don't have elements in the same order");
1150    }
1151
1152    transformations_ = new CGridTransformation(transformedGrid, this);
1153    transformations_->computeTransformationMapping();
1154    std::cout << "send index " << *(transformations_->getLocalIndexToSendFromGridSource()[0]) << std::endl;
1155    std::cout << "receive index " << *(transformations_->getLocalIndexToReceiveOnGridDest()[0][0]) << std::endl;
1156  }
1157
1158  /*!
1159  \brief Get the list of domain pointers
1160  \return list of domain pointers
1161  */
1162  std::vector<CDomain*> CGrid::getDomains()
1163  {
1164    std::vector<CDomain*> domList;
1165    if (!domList_.empty())
1166    {
1167      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1168    }
1169    return domList;
1170  }
1171
1172  /*!
1173  \brief Get the list of  axis pointers
1174  \return list of axis pointers
1175  */
1176  std::vector<CAxis*> CGrid::getAxis()
1177  {
1178    std::vector<CAxis*> aList;
1179    if (!axisList_.empty())
1180      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1181
1182    return aList;
1183  }
1184
1185  /*!
1186  \brief Set domain(s) of a grid from a list
1187  \param[in] domains list of domains
1188  */
1189  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1190  {
1191    if (isDomListSet) return;
1192    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1193    if (!domains.empty() && domList.empty()) domList = domains;
1194    if (!domList.empty())
1195    {
1196      int sizeDom = domList.size();
1197      domList_.resize(sizeDom);
1198      for (int i = 0 ; i < sizeDom; ++i)
1199      {
1200        domList_[i] = domList[i]->getId();
1201      }
1202      isDomListSet = true;
1203    }
1204
1205  }
1206
1207  /*!
1208  \brief Set axis(s) of a grid from a list
1209  \param[in] axis list of axis
1210  */
1211  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1212  {
1213    if (isAxisListSet) return;
1214    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1215    if (!axis.empty() && aList.empty()) aList = axis;
1216    if (!aList.empty())
1217    {
1218      int sizeAxis = aList.size();
1219      axisList_.resize(sizeAxis);
1220      for (int i = 0; i < sizeAxis; ++i)
1221      {
1222        axisList_[i] = aList[i]->getId();
1223      }
1224      isAxisListSet = true;
1225    }
1226  }
1227
1228  /*!
1229  \brief Get list of id of domains
1230  \return id list of domains
1231  */
1232  std::vector<StdString> CGrid::getDomainList()
1233  {
1234    setDomainList();
1235    return domList_;
1236  }
1237
1238  /*!
1239  \brief Get list of id of axis
1240  \return id list of axis
1241  */
1242  std::vector<StdString> CGrid::getAxisList()
1243  {
1244    setAxisList();
1245    return axisList_;
1246  }
1247
1248  void CGrid::sendAllDomains()
1249  {
1250    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1251    int dSize = domList.size();
1252    for (int i = 0; i < dSize; ++i)
1253    {
1254      sendAddDomain(domList[i]->getId());
1255      domList[i]->sendAllAttributesToServer();
1256    }
1257  }
1258
1259  void CGrid::sendAllAxis()
1260  {
1261    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1262    int aSize = aList.size();
1263
1264    for (int i = 0; i < aSize; ++i)
1265    {
1266      sendAddAxis(aList[i]->getId());
1267      aList[i]->sendAllAttributesToServer();
1268    }
1269  }
1270
1271  void CGrid::parse(xml::CXMLNode & node)
1272  {
1273    SuperClass::parse(node);
1274
1275    // List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false)
1276    std::vector<bool> order;
1277
1278    if (node.goToChildElement())
1279    {
1280      StdString domainName("domain");
1281      StdString axisName("axis");
1282      do
1283      {
1284        if (node.getElementName() == domainName) {
1285          order.push_back(true);
1286          this->getVirtualDomainGroup()->parseChild(node);
1287        }
1288        if (node.getElementName() == axisName) {
1289          order.push_back(false);
1290          this->getVirtualAxisGroup()->parseChild(node);
1291        }
1292      } while (node.goToNextElement()) ;
1293      node.goToParentElement();
1294    }
1295
1296    if (!order.empty())
1297    {
1298      int sizeOrd = order.size();
1299      axis_domain_order.resize(sizeOrd);
1300      for (int i = 0; i < sizeOrd; ++i)
1301      {
1302        axis_domain_order(i) = order[i];
1303      }
1304    }
1305
1306    setDomainList();
1307    setAxisList();
1308   }
1309
1310} // namespace xios
Note: See TracBrowser for help on using the repository browser.