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

Last change on this file since 656 was 656, checked in by rlacroix, 7 years ago

Grid: Release all allocated memory.

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