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

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

Implementing transformation algorithm: zoom axis (local commit)

+) Implement zoom axis: zoomed points are points not masked
+) Correct some minor bugs

Test
+) Ok with normal cases: zoom in the last of transformation list
+) There is still a bug in case of zoom then inverse

  • 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: 41.6 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   void CGrid::modifyMask(const CArray<int,1>& indexToModify)
302   {
303      using namespace std;
304      std::vector<CDomain*> domainP = this->getDomains();
305      std::vector<CAxis*> axisP = this->getAxis();
306      int dim = domainP.size() * 2 + axisP.size();
307
308      switch (dim) {
309        case 1:
310          modifyGridMask(mask1, indexToModify);
311          break;
312        case 2:
313          modifyGridMask(mask2, indexToModify);
314          break;
315        case 3:
316          modifyGridMask(mask3, indexToModify);
317          break;
318
319        default:
320          break;
321      }
322   }
323
324   //---------------------------------------------------------------
325
326   void CGrid::solveDomainRef(bool sendAtt)
327   {
328      setDomainList();
329      std::vector<CDomain*> domListP = this->getDomains();
330      if (!domListP.empty())
331      {
332        computeGridGlobalDimension(getDomains(), getAxis(), axis_domain_order);
333        for (int i = 0; i < domListP.size(); ++i)
334        {
335          if (sendAtt) domListP[i]->sendCheckedAttributes();
336          else domListP[i]->checkAttributesOnClient();
337        }
338      }
339   }
340
341   //---------------------------------------------------------------
342
343   void CGrid::solveAxisRef(bool sendAtt)
344   {
345      setAxisList();
346      std::vector<CAxis*> axisListP = this->getAxis();
347      if (!axisListP.empty())
348      {
349        int idx = 0;
350        axisPositionInGrid_.resize(0);
351        for (int i = 0; i < axis_domain_order.numElements(); ++i)
352        {
353          if (false == axis_domain_order(i))
354          {
355            axisPositionInGrid_.push_back(idx);
356            ++idx;
357          }
358          else idx += 2;
359        }
360
361        computeGridGlobalDimension(getDomains(), getAxis(), axis_domain_order);
362        for (int i = 0; i < axisListP.size(); ++i)
363        {
364          if (sendAtt)
365            axisListP[i]->sendCheckedAttributes(globalDim_,axisPositionInGrid_[i]);
366          else
367            axisListP[i]->checkAttributesOnClient(globalDim_,axisPositionInGrid_[i]);
368          ++idx;
369        }
370
371      }
372   }
373
374   std::vector<int> CGrid::getAxisPositionInGrid() const
375   {
376     return axisPositionInGrid_;
377   }
378
379
380   //---------------------------------------------------------------
381
382   void CGrid::computeIndex(void)
383   {
384     CContext* context = CContext::getCurrent() ;
385     CContextClient* client=context->client ;
386
387     // First of all, compute distribution on client side
388     clientDistribution_ = new CDistributionClient(client->clientRank, this);
389     // Get local data index on client
390     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().numElements());
391     storeIndex_client = (clientDistribution_->getLocalDataIndexOnClient());
392     isDataDistributed_= clientDistribution_->isDataDistributed();
393
394     if (!doGridHaveDataDistributed())
395     {
396        if (0 == client->clientRank)
397        {
398          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().numElements();
399          for (int rank = 0; rank < client->serverSize; ++rank)
400            connectedDataSize_[rank] = ssize;
401        }
402        return;
403     }
404
405     // Compute mapping between client and server
406     size_t globalSizeIndex = 1, indexBegin, indexEnd;
407     int range, clientSize = client->clientSize;
408     for (int i = 0; i < globalDim_.size(); ++i) globalSizeIndex *= globalDim_[i];
409     indexBegin = 0;
410     for (int i = 0; i < clientSize; ++i)
411     {
412       range = globalSizeIndex / clientSize;
413       if (i < (globalSizeIndex%clientSize)) ++range;
414       if (i == client->clientRank) break;
415       indexBegin += range;
416     }
417     indexEnd = indexBegin + range - 1;
418
419     // Then compute distribution on server side
420     serverDistributionDescription_ = new CServerDistributionDescription(clientDistribution_->getNGlob());
421     serverDistributionDescription_->computeServerDistribution(client->serverSize, true);
422     serverDistributionDescription_->computeServerGlobalIndexInRange(client->serverSize,
423                                                                     std::make_pair<size_t,size_t>(indexBegin, indexEnd));
424
425     // Finally, compute index mapping between client(s) and server(s)
426     clientServerMap_ = new CClientServerMappingDistributed(serverDistributionDescription_->getGlobalIndexRange(),
427                                                            client->intraComm,
428                                                            clientDistribution_->isDataDistributed());
429
430     clientServerMap_->computeServerIndexMapping(clientDistribution_->getGlobalIndex());
431     const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
432     const CArray<size_t,1>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
433
434     std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
435     itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
436     iteGlobalMap = globalIndexOnServer.end();
437
438     int nbGlobalIndex = globalIndexSendToServer.numElements();
439    for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
440    {
441      int serverRank = itGlobalMap->first;
442      std::vector<size_t>::const_iterator itbVecGlobal = (itGlobalMap->second).begin(), itVecGlobal,
443                                          iteVecGlobal = (itGlobalMap->second).end();
444      for (int i = 0; i < nbGlobalIndex; ++i)
445      {
446        if (iteVecGlobal != std::find(itbVecGlobal, iteVecGlobal, globalIndexSendToServer(i)))
447        {
448          if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
449            connectedDataSize_[serverRank] = 1;
450          else
451            ++connectedDataSize_[serverRank];
452        }
453      }
454    }
455
456   connectedServerRank_.clear();
457   for (std::map<int, std::vector<size_t> >::const_iterator it = globalIndexOnServer.begin(); it != globalIndexOnServer.end(); ++it) {
458     connectedServerRank_.push_back(it->first);
459   }
460   if (!connectedDataSize_.empty())
461   {
462     connectedServerRank_.clear();
463     for (std::map<int,size_t>::const_iterator it = connectedDataSize_.begin(); it != connectedDataSize_.end(); ++it)
464       connectedServerRank_.push_back(it->first);
465   }
466
467    nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
468   }
469
470   //----------------------------------------------------------------
471
472   CGrid* CGrid::createGrid(CDomain* domain)
473   {
474      std::vector<CDomain*> vecDom(1,domain);
475      std::vector<CAxis*> vecAxis;
476      CArray<bool,1> axisDomainOrder;
477      CGrid* grid = createGrid(vecDom, vecAxis, axisDomainOrder);
478
479      return (grid);
480   }
481
482   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
483   {
484      std::vector<CDomain*> vecDom(1,domain);
485      std::vector<CAxis*> vecAxis(1,axis);
486      CArray<bool,1> axisDomainOrder;
487      CGrid* grid = createGrid(vecDom, vecAxis, axisDomainOrder);
488
489      return (grid);
490   }
491
492   CGrid* CGrid::createGrid(std::vector<CDomain*> domains, std::vector<CAxis*> axis, CArray<bool,1> axisDomainOrder)
493   {
494      StdString new_id = StdString("__");
495      if (!domains.empty()) for (int i = 0; i < domains.size(); ++i) new_id += domains[i]->getId() + StdString("_");
496      if (!axis.empty()) for (int i = 0; i < axis.size(); ++i) new_id += axis[i]->getId() + StdString("_") ;
497      if (domains.empty() && axis.empty()) new_id += StdString("scalar_grid");
498      new_id += StdString("_");
499
500      CGrid* grid = CGridGroup::get("grid_definition")->createChild(new_id) ;
501      grid->setDomainList(domains);
502      grid->setAxisList(axis);
503
504      //By default, domains are always the first ones of a grid
505      if (0 == axisDomainOrder.numElements())
506      {
507        int size = domains.size()+axis.size();
508        grid->axis_domain_order.resize(size);
509        for (int i = 0; i < size; ++i)
510        {
511          if (i < domains.size()) grid->axis_domain_order(i) = true;
512          else grid->axis_domain_order(i) = false;
513        }
514      }
515      else
516      {
517        grid->axis_domain_order.resize(axisDomainOrder.numElements());
518        grid->axis_domain_order = axisDomainOrder;
519      }
520
521      grid->computeGridGlobalDimension(domains, axis, grid->axis_domain_order);
522
523      return (grid);
524   }
525
526   CDomainGroup* CGrid::getVirtualDomainGroup() const
527   {
528     return (this->vDomainGroup_);
529   }
530
531   CAxisGroup* CGrid::getVirtualAxisGroup() const
532   {
533     return (this->vAxisGroup_);
534   }
535
536   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
537   {
538     CArray<size_t,1>& out_i=*outIndexFromClient[rank];
539     StdSize numElements = stored.numElements();
540     for (StdSize n = 0; n < numElements; ++n)
541     {
542       *(field+out_i(n)) = stored(n);
543     }
544   }
545
546   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
547   {
548     CArray<size_t,1>& out_i = *outIndexFromClient[rank];
549     StdSize numElements = stored.numElements();
550     for (StdSize n = 0; n < numElements; ++n)
551     {
552       stored(n) = *(field+out_i(n));
553     }
554   }
555
556   //----------------------------------------------------------------
557
558
559   void CGrid::storeField_arr
560      (const double * const data, CArray<double, 1>& stored) const
561   {
562      const StdSize size = storeIndex_client.numElements() ;
563
564      stored.resize(size) ;
565      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)] ;
566   }
567
568   void CGrid::restoreField_arr
569      (const CArray<double, 1>& stored, double * const data) const
570   {
571      const StdSize size = storeIndex_client.numElements() ;
572
573      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i) ;
574   }
575
576  void CGrid::computeIndexScalarGrid()
577  {
578    CContext* context = CContext::getCurrent();
579    CContextClient* client=context->client;
580
581    storeIndex_client.resize(1);
582    storeIndex_client[0] = 0;
583    if (0 == client->clientRank)
584    {
585      for (int rank = 0; rank < client->serverSize; ++rank)
586        connectedDataSize_[rank] = 1;
587    }
588    isDataDistributed_ = false;
589  }
590
591  void CGrid::sendIndexScalarGrid()
592  {
593    CContext* context = CContext::getCurrent() ;
594    CContextClient* client=context->client ;
595
596    CEventClient event(getType(),EVENT_ID_INDEX);
597    list<shared_ptr<CMessage> > list_msg ;
598    list< CArray<size_t,1>* > listOutIndex;
599    if (0 == client->clientRank)
600    {
601      for (int rank = 0; rank < client->serverSize; ++rank)
602      {
603        int nb = 1;
604        CArray<size_t, 1> outGlobalIndexOnServer(nb);
605        CArray<int, 1> outLocalIndexToServer(nb);
606        for (int k = 0; k < nb; ++k)
607        {
608          outGlobalIndexOnServer(k) = 0;
609          outLocalIndexToServer(k)  = 0;
610        }
611
612        storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer) ));
613        listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
614
615        list_msg.push_back(shared_ptr<CMessage>(new CMessage));
616        *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
617
618        event.push(rank, 1, *list_msg.back());
619      }
620      client->sendEvent(event);
621    }
622    else
623      client->sendEvent(event);
624
625    for(list<CArray<size_t,1>* >::iterator it=listOutIndex.begin();it!=listOutIndex.end();++it) delete *it ;
626  }
627
628  void CGrid::sendIndex(void)
629  {
630    CContext* context = CContext::getCurrent() ;
631    CContextClient* client=context->client ;
632
633    CEventClient event(getType(),EVENT_ID_INDEX) ;
634    int rank ;
635    list<shared_ptr<CMessage> > list_msg ;
636    list< CArray<size_t,1>* > listOutIndex;
637    const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
638    const CArray<int,1>& localIndexSendToServer = clientDistribution_->getLocalDataIndexSendToServer();
639    const CArray<size_t,1>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
640
641    if (!doGridHaveDataDistributed())
642    {
643      if (0 == client->clientRank)
644      {
645        CArray<size_t, 1> outGlobalIndexOnServer = globalIndexSendToServer;
646        CArray<int,1> outLocalIndexToServer = localIndexSendToServer;
647        for (rank = 0; rank < client->serverSize; ++rank)
648        {
649          storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer)));
650          listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
651
652          list_msg.push_back(shared_ptr<CMessage>(new CMessage));
653          *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
654
655          event.push(rank, 1, *list_msg.back());
656        }
657        client->sendEvent(event);
658      }
659      else
660        client->sendEvent(event);
661    }
662    else
663    {
664      std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
665      itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
666      iteGlobalMap = globalIndexOnServer.end();
667
668      int nbGlobalIndex = globalIndexSendToServer.numElements();
669      std::map<int,std::vector<int> >localIndexTmp;
670      std::map<int,std::vector<size_t> > globalIndexTmp;
671      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
672      {
673        int serverRank = itGlobalMap->first;
674        std::vector<size_t>::const_iterator itbVecGlobal = (itGlobalMap->second).begin(),
675                                            iteVecGlobal = (itGlobalMap->second).end();
676        for (int i = 0; i < nbGlobalIndex; ++i)
677        {
678          if (iteVecGlobal != std::find(itbVecGlobal, iteVecGlobal, globalIndexSendToServer(i)))
679          {
680            globalIndexTmp[serverRank].push_back(globalIndexSendToServer(i));
681            localIndexTmp[serverRank].push_back(localIndexSendToServer(i));
682          }
683        }
684      }
685
686      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
687      {
688        rank = connectedServerRank_[ns];
689        int nb = 0;
690        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
691          nb = globalIndexTmp[rank].size();
692
693        CArray<size_t, 1> outGlobalIndexOnServer(nb);
694        CArray<int, 1> outLocalIndexToServer(nb);
695        for (int k = 0; k < nb; ++k)
696        {
697          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
698          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
699        }
700
701        storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer) ));
702        listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
703
704        list_msg.push_back(shared_ptr<CMessage>(new CMessage));
705        *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
706
707        event.push(rank, nbSenders[rank], *list_msg.back());
708      }
709
710      client->sendEvent(event);
711    }
712
713    for(list<CArray<size_t,1>* >::iterator it=listOutIndex.begin();it!=listOutIndex.end();++it) delete *it ;
714  }
715
716  void CGrid::recvIndex(CEventServer& event)
717  {
718    string gridId;
719    vector<int> ranks;
720    vector<CBufferIn*> buffers;
721
722    list<CEventServer::SSubEvent>::iterator it;
723    for (it=event.subEvents.begin();it!=event.subEvents.end();++it)
724    {
725      ranks.push_back(it->rank);
726      CBufferIn* buffer = it->buffer;
727      *buffer >> gridId;
728      buffers.push_back(buffer);
729    }
730    get(gridId)->recvIndex(ranks, buffers) ;
731  }
732
733  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
734                                         const std::vector<CAxis*>& axis,
735                                         const CArray<bool,1>& axisDomainOrder)
736  {
737    globalDim_.resize(domains.size()*2+axis.size());
738    int idx = 0, idxDomain = 0, idxAxis = 0;
739    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
740    {
741      if (axisDomainOrder(i))
742      {
743        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
744        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
745        ++idxDomain;
746        idx += 2;
747      }
748      else
749      {
750        globalDim_[idx] = axis[idxAxis]->size.getValue();
751        ++idxAxis;
752        ++idx;
753      }
754    }
755  }
756
757  std::vector<int> CGrid::getGlobalDimension()
758  {
759    return globalDim_;
760  }
761
762  bool CGrid::isScalarGrid() const
763  {
764    return (axisList_.empty() && domList_.empty());
765  }
766
767  /*!
768    Verify whether one server need to write data
769    There are some cases on which one server has nodata to write. For example, when we
770  just only want to zoom on a domain.
771  */
772  bool CGrid::doGridHaveDataToWrite()
773  {
774    size_t ssize = 0;
775    for (map<int, CArray<size_t, 1>* >::const_iterator it = outIndexFromClient.begin();
776                                                       it != outIndexFromClient.end(); ++it)
777    {
778      ssize += (it->second)->numElements();
779    }
780    return (0 != ssize);
781  }
782
783  /*!
784    Return size of data which is written on each server
785    Whatever dimension of a grid, data which are written on server must be presented as
786  an one dimension array.
787  \return size of data written on server
788  */
789  size_t CGrid::getWrittenDataSize() const
790  {
791    return writtenDataSize_;
792  }
793
794  const CDistributionServer* CGrid::getDistributionServer() const
795  {
796    return serverDistribution_;
797  }
798
799  const CDistributionClient* CGrid::getDistributionClient() const
800  {
801    return clientDistribution_;
802  }
803
804  bool CGrid::doGridHaveDataDistributed()
805  {
806    if (isScalarGrid()) return false;
807    else
808      return isDataDistributed_;
809  }
810
811  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
812  {
813    CContext* context = CContext::getCurrent();
814    CContextServer* server = context->server;
815
816    for (int n = 0; n < ranks.size(); n++)
817    {
818      int rank = ranks[n];
819      CBufferIn& buffer = *buffers[n];
820
821      buffer >> isDataDistributed_;
822      size_t dataSize = 0;
823
824      if (isScalarGrid())
825      {
826        writtenDataSize_ = 1;
827        CArray<size_t,1> outIndex;
828        buffer >> outIndex;
829        outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
830        std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
831        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
832                                                      nZoomBeginGlobal, nGlob);
833        return;
834      }
835
836      if (0 == serverDistribution_)
837      {
838        int idx = 0, numElement = axis_domain_order.numElements();
839        int ssize = numElement;
840        std::vector<int> indexMap(numElement);
841        for (int i = 0; i < numElement; ++i)
842        {
843          indexMap[i] = idx;
844          if (true == axis_domain_order(i))
845          {
846            ++ssize;
847            idx += 2;
848          }
849          else
850            ++idx;
851        }
852
853        int axisId = 0, domainId = 0;
854        std::vector<CDomain*> domainList = getDomains();
855        std::vector<CAxis*> axisList = getAxis();
856        std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
857        for (int i = 0; i < numElement; ++i)
858        {
859          if (axis_domain_order(i))
860          {
861            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
862            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
863            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->zoom_ibegin;
864            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
865
866            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
867            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
868            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin;
869            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
870            ++domainId;
871          }
872          else
873          {
874            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
875            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
876            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;
877            nGlob[indexMap[i]] = axisList[axisId]->size;
878            ++axisId;
879          }
880        }
881        dataSize = 1;
882        for (int i = 0; i < nZoomSize.size(); ++i)
883          dataSize *= nZoomSize[i];
884
885        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
886                                                      nZoomBeginGlobal, nGlob);
887      }
888
889      CArray<size_t,1> outIndex;
890      buffer >> outIndex;
891      if (isDataDistributed_)
892        serverDistribution_->computeLocalIndex(outIndex);
893      else
894      {
895        dataSize = outIndex.numElements();
896        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
897      }
898      writtenDataSize_ += dataSize;
899
900      outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
901      connectedDataSize_[rank] = outIndex.numElements();
902    }
903
904    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
905  }
906
907   /*!
908   \brief Dispatch event received from client
909      Whenever a message is received in buffer of server, it will be processed depending on
910   its event type. A new event type should be added in the switch list to make sure
911   it processed on server side.
912   \param [in] event: Received message
913   */
914  bool CGrid::dispatchEvent(CEventServer& event)
915  {
916
917    if (SuperClass::dispatchEvent(event)) return true ;
918    else
919    {
920      switch(event.type)
921      {
922        case EVENT_ID_INDEX :
923          recvIndex(event) ;
924          return true ;
925          break ;
926
927         case EVENT_ID_ADD_DOMAIN :
928           recvAddDomain(event) ;
929           return true ;
930           break ;
931
932         case EVENT_ID_ADD_AXIS :
933           recvAddAxis(event) ;
934           return true ;
935           break ;
936        default :
937          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
938                <<"Unknown Event") ;
939          return false ;
940      }
941    }
942  }
943
944   void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const
945   {
946      if ((this->storeIndex.size()-1 ) != storedClient.size())
947         ERROR("void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const",
948                << "[ Expected received field = " << (this->storeIndex.size()-1) << ", "
949                << "[ received fiedl = "    << storedClient.size() << "] "
950                << "Data from clients are missing!") ;
951      storedServer.resize(storeIndex[0]->numElements());
952
953      for (StdSize i = 0, n = 0; i < storedClient.size(); i++)
954         for (StdSize j = 0; j < storedClient[i]->numElements(); j++)
955            storedServer(n++) = (*storedClient[i])(j);
956   }
957
958   void CGrid::outputFieldToServer(CArray<double,1>& fieldIn, int rank, CArray<double,1>& fieldOut)
959   {
960     CArray<int,1>& index = *storeIndex_toSrv[rank] ;
961     int nb=index.numElements() ;
962     fieldOut.resize(nb) ;
963
964     for(int k=0;k<nb;k++) fieldOut(k)=fieldIn(index(k)) ;
965    }
966   ///---------------------------------------------------------------
967
968   CDomain* CGrid::addDomain(const std::string& id)
969   {
970     return vDomainGroup_->createChild(id) ;
971   }
972
973   CAxis* CGrid::addAxis(const std::string& id)
974   {
975     return vAxisGroup_->createChild(id) ;
976   }
977
978   //! Change virtual field group to a new one
979   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
980   {
981      this->vDomainGroup_ = newVDomainGroup;
982   }
983
984   //! Change virtual variable group to new one
985   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
986   {
987      this->vAxisGroup_ = newVAxisGroup;
988   }
989
990   //----------------------------------------------------------------
991   //! Create virtual field group, which is done normally on initializing file
992   void CGrid::setVirtualDomainGroup(void)
993   {
994      this->setVirtualDomainGroup(CDomainGroup::create());
995   }
996
997   //! Create virtual variable group, which is done normally on initializing file
998   void CGrid::setVirtualAxisGroup(void)
999   {
1000      this->setVirtualAxisGroup(CAxisGroup::create());
1001   }
1002
1003   /*!
1004   \brief Send a message to create a domain on server side
1005   \param[in] id String identity of domain that will be created on server
1006   */
1007   void CGrid::sendAddDomain(const string& id)
1008   {
1009    CContext* context=CContext::getCurrent() ;
1010
1011    if (! context->hasServer )
1012    {
1013       CContextClient* client=context->client ;
1014
1015       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN) ;
1016       if (client->isServerLeader())
1017       {
1018         CMessage msg ;
1019         msg<<this->getId() ;
1020         msg<<id ;
1021         const std::list<int>& ranks = client->getRanksServerLeader();
1022         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1023           event.push(*itRank,1,msg);
1024         client->sendEvent(event) ;
1025       }
1026       else client->sendEvent(event) ;
1027    }
1028   }
1029
1030   /*!
1031   \brief Send a message to create an axis on server side
1032   \param[in] id String identity of axis that will be created on server
1033   */
1034   void CGrid::sendAddAxis(const string& id)
1035   {
1036    CContext* context=CContext::getCurrent() ;
1037
1038    if (! context->hasServer )
1039    {
1040       CContextClient* client=context->client ;
1041
1042       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS) ;
1043       if (client->isServerLeader())
1044       {
1045         CMessage msg ;
1046         msg<<this->getId() ;
1047         msg<<id ;
1048         const std::list<int>& ranks = client->getRanksServerLeader();
1049         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1050           event.push(*itRank,1,msg);
1051         client->sendEvent(event) ;
1052       }
1053       else client->sendEvent(event) ;
1054    }
1055   }
1056
1057   /*!
1058   \brief Receive a message annoucing the creation of a domain on server side
1059   \param[in] event Received event
1060   */
1061   void CGrid::recvAddDomain(CEventServer& event)
1062   {
1063
1064      CBufferIn* buffer=event.subEvents.begin()->buffer;
1065      string id;
1066      *buffer>>id ;
1067      get(id)->recvAddDomain(*buffer) ;
1068   }
1069
1070   /*!
1071   \brief Receive a message annoucing the creation of a domain on server side
1072   \param[in] buffer Buffer containing message
1073   */
1074   void CGrid::recvAddDomain(CBufferIn& buffer)
1075   {
1076      string id ;
1077      buffer>>id ;
1078      addDomain(id) ;
1079   }
1080
1081   /*!
1082   \brief Receive a message annoucing the creation of an axis on server side
1083   \param[in] event Received event
1084   */
1085   void CGrid::recvAddAxis(CEventServer& event)
1086   {
1087
1088      CBufferIn* buffer=event.subEvents.begin()->buffer;
1089      string id;
1090      *buffer>>id ;
1091      get(id)->recvAddAxis(*buffer) ;
1092   }
1093
1094   /*!
1095   \brief Receive a message annoucing the creation of an axis on server side
1096   \param[in] buffer Buffer containing message
1097   */
1098   void CGrid::recvAddAxis(CBufferIn& buffer)
1099   {
1100      string id ;
1101      buffer>>id ;
1102      addAxis(id) ;
1103   }
1104
1105  /*!
1106  \brief Solve domain and axis references
1107  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1108  all attributes from their parents, they should be processed with this function
1109  \param[in] apply inherit all attributes of parents (true)
1110  */
1111  void CGrid::solveDomainAxisRefInheritance(bool apply)
1112  {
1113    CContext* context = CContext::getCurrent();
1114    unsigned int vecSize, i;
1115    std::vector<StdString>::iterator it, itE;
1116    setDomainList();
1117    it = domList_.begin(); itE = domList_.end();
1118    for (; it != itE; ++it)
1119    {
1120      CDomain* pDom = CDomain::get(*it);
1121      if (context->hasClient)
1122      {
1123        pDom->solveRefInheritance(apply);
1124        pDom->solveBaseReference();
1125        if ((!pDom->domain_ref.isEmpty()) && (pDom->name.isEmpty()))
1126          pDom->name.setValue(pDom->getBaseDomainReference()->getId());
1127      }
1128    }
1129
1130    setAxisList();
1131    it = axisList_.begin(); itE = axisList_.end();
1132    for (; it != itE; ++it)
1133    {
1134      CAxis* pAxis = CAxis::get(*it);
1135      if (context->hasClient)
1136      {
1137        pAxis->solveRefInheritance(apply);
1138        pAxis->solveBaseReference();
1139        pAxis->solveInheritanceTransformation();
1140        if ((!pAxis->axis_ref.isEmpty()) && (pAxis->name.isEmpty()))
1141          pAxis->name.setValue(pAxis->getBaseAxisReference()->getId());
1142      }
1143    }
1144  }
1145
1146  bool CGrid::isTransformed()
1147  {
1148    return isTransformed_;
1149  }
1150
1151  void CGrid::setTransformed()
1152  {
1153    isTransformed_ = true;
1154  }
1155
1156  CGridTransformation* CGrid::getTransformations()
1157  {
1158    return transformations_;
1159  }
1160
1161  void CGrid::transformGrid(CGrid* transformedGrid)
1162  {
1163    if (transformedGrid->isTransformed()) return;
1164    transformedGrid->setTransformed();
1165    if (axis_domain_order.numElements() != transformedGrid->axis_domain_order.numElements())
1166    {
1167      ERROR("CGrid::transformGrid(CGrid* transformedGrid)",
1168           << "Two grids have different dimension size"
1169           << "Dimension of grid source " <<this->getId() << " is " << axis_domain_order.numElements() << std::endl
1170           << "Dimension of grid destination " <<transformedGrid->getId() << " is " << transformedGrid->axis_domain_order.numElements());
1171    }
1172    else
1173    {
1174      int ssize = axis_domain_order.numElements();
1175      for (int i = 0; i < ssize; ++i)
1176        if (axis_domain_order(i) != (transformedGrid->axis_domain_order)(i))
1177          ERROR("CGrid::transformGrid(CGrid* transformedGrid)",
1178                << "Grids " <<this->getId() <<" and " << transformedGrid->getId()
1179                << " don't have elements in the same order");
1180    }
1181
1182    transformations_ = new CGridTransformation(transformedGrid, this);
1183    transformations_->computeAll();
1184
1185    // Ok, now need to compute index of grid source
1186    checkMaskIndex(false);
1187  }
1188
1189  /*!
1190  \brief Get the list of domain pointers
1191  \return list of domain pointers
1192  */
1193  std::vector<CDomain*> CGrid::getDomains()
1194  {
1195    std::vector<CDomain*> domList;
1196    if (!domList_.empty())
1197    {
1198      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1199    }
1200    return domList;
1201  }
1202
1203  /*!
1204  \brief Get the list of  axis pointers
1205  \return list of axis pointers
1206  */
1207  std::vector<CAxis*> CGrid::getAxis()
1208  {
1209    std::vector<CAxis*> aList;
1210    if (!axisList_.empty())
1211      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1212
1213    return aList;
1214  }
1215
1216  /*!
1217  \brief Set domain(s) of a grid from a list
1218  \param[in] domains list of domains
1219  */
1220  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1221  {
1222    if (isDomListSet) return;
1223    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1224    if (!domains.empty() && domList.empty()) domList = domains;
1225    if (!domList.empty())
1226    {
1227      int sizeDom = domList.size();
1228      domList_.resize(sizeDom);
1229      for (int i = 0 ; i < sizeDom; ++i)
1230      {
1231        domList_[i] = domList[i]->getId();
1232      }
1233      isDomListSet = true;
1234    }
1235
1236  }
1237
1238  /*!
1239  \brief Set axis(s) of a grid from a list
1240  \param[in] axis list of axis
1241  */
1242  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1243  {
1244    if (isAxisListSet) return;
1245    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1246    if (!axis.empty() && aList.empty()) aList = axis;
1247    if (!aList.empty())
1248    {
1249      int sizeAxis = aList.size();
1250      axisList_.resize(sizeAxis);
1251      for (int i = 0; i < sizeAxis; ++i)
1252      {
1253        axisList_[i] = aList[i]->getId();
1254      }
1255      isAxisListSet = true;
1256    }
1257  }
1258
1259  /*!
1260  \brief Get list of id of domains
1261  \return id list of domains
1262  */
1263  std::vector<StdString> CGrid::getDomainList()
1264  {
1265    setDomainList();
1266    return domList_;
1267  }
1268
1269  /*!
1270  \brief Get list of id of axis
1271  \return id list of axis
1272  */
1273  std::vector<StdString> CGrid::getAxisList()
1274  {
1275    setAxisList();
1276    return axisList_;
1277  }
1278
1279  void CGrid::sendAllDomains()
1280  {
1281    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1282    int dSize = domList.size();
1283    for (int i = 0; i < dSize; ++i)
1284    {
1285      sendAddDomain(domList[i]->getId());
1286      domList[i]->sendAllAttributesToServer();
1287    }
1288  }
1289
1290  void CGrid::sendAllAxis()
1291  {
1292    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1293    int aSize = aList.size();
1294
1295    for (int i = 0; i < aSize; ++i)
1296    {
1297      sendAddAxis(aList[i]->getId());
1298      aList[i]->sendAllAttributesToServer();
1299    }
1300  }
1301
1302  void CGrid::parse(xml::CXMLNode & node)
1303  {
1304    SuperClass::parse(node);
1305
1306    // List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false)
1307    std::vector<bool> order;
1308
1309    if (node.goToChildElement())
1310    {
1311      StdString domainName("domain");
1312      StdString axisName("axis");
1313      do
1314      {
1315        if (node.getElementName() == domainName) {
1316          order.push_back(true);
1317          this->getVirtualDomainGroup()->parseChild(node);
1318        }
1319        if (node.getElementName() == axisName) {
1320          order.push_back(false);
1321          this->getVirtualAxisGroup()->parseChild(node);
1322        }
1323      } while (node.goToNextElement()) ;
1324      node.goToParentElement();
1325    }
1326
1327    if (!order.empty())
1328    {
1329      int sizeOrd = order.size();
1330      axis_domain_order.resize(sizeOrd);
1331      for (int i = 0; i < sizeOrd; ++i)
1332      {
1333        axis_domain_order(i) = order[i];
1334      }
1335    }
1336
1337    setDomainList();
1338    setAxisList();
1339   }
1340
1341} // namespace xios
Note: See TracBrowser for help on using the repository browser.