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

Last change on this file since 671 was 671, checked in by rlacroix, 6 years ago

Avoid using C++11 feature for now.

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