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

Last change on this file since 595 was 595, checked in by rlacroix, 9 years ago

Allow using more servers than clients.

This will be useful later when implementing server to client communications.

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