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

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

Making changes in domain to make sure unstructed grid work with new method of index distribution

+) Change the way define i_index and j_index of a domain
+) Remove some redundant attributes of domain
+) Adjust the way to calculate index distribution on server side

Test
+) Make some minor change to test_unstruct_complete to work with new XIOS
+) On Curie
+) All test pass and correct

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