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

Last change on this file since 586 was 586, checked in by mhnguyen, 7 years ago

Fixing some bugs on writting non-distributed data

+) Implement scalar grid: Allow to send scalar real data
+) Modify the way to compute the mapping of buffer size from one client to a server
+) Fix a bug of writting axis on one_file mode
+) Make some changes in test_new_features.f90 and test_complete.f90

Test
+) On Curie,
+) test_client and test_complete pass and results are 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: 37.5 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 "xmlioserver_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] = 0;
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->axisDomainOrder);
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::computeIndexScalarGrid()
522  {
523    CContext* context = CContext::getCurrent();
524    CContextClient* client=context->client;
525
526    storeIndex_client.resize(1);
527    storeIndex_client[0] = 0;
528    if (0 == client->clientRank)
529    {
530      for (int rank = 0; rank < client->serverSize; ++rank)
531        connectedDataSize_[rank] = 1;
532    }
533    isDataDistributed_ = false;
534  }
535
536  void CGrid::sendIndexScalarGrid()
537  {
538    CContext* context = CContext::getCurrent() ;
539    CContextClient* client=context->client ;
540
541    CEventClient event(getType(),EVENT_ID_INDEX);
542    list<shared_ptr<CMessage> > list_msg ;
543    list< CArray<size_t,1>* > listOutIndex;
544    if (0 == client->clientRank)
545    {
546      for (int rank = 0; rank < client->serverSize; ++rank)
547      {
548        int nb = 1;
549        CArray<size_t, 1> outGlobalIndexOnServer(nb);
550        CArray<int, 1> outLocalIndexToServer(nb);
551        for (int k = 0; k < nb; ++k)
552        {
553          outGlobalIndexOnServer(k) = 0;
554          outLocalIndexToServer(k)  = 0;
555        }
556
557        storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer) ));
558        listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
559
560        list_msg.push_back(shared_ptr<CMessage>(new CMessage));
561        *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
562
563        event.push(rank, 1, *list_msg.back());
564      }
565      client->sendEvent(event);
566    }
567    else
568      client->sendEvent(event);
569
570    for(list<CArray<size_t,1>* >::iterator it=listOutIndex.begin();it!=listOutIndex.end();++it) delete *it ;
571  }
572
573  void CGrid::sendIndex(void)
574  {
575    CContext* context = CContext::getCurrent() ;
576    CContextClient* client=context->client ;
577
578    CEventClient event(getType(),EVENT_ID_INDEX) ;
579    int rank ;
580    list<shared_ptr<CMessage> > list_msg ;
581    list< CArray<size_t,1>* > listOutIndex;
582    const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
583    const CArray<int,1>& localIndexSendToServer = clientDistribution_->getLocalDataIndexSendToServer();
584    const CArray<size_t,1>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
585
586    if (!doGridHaveDataDistributed())
587    {
588      if (0 == client->clientRank)
589      {
590        CArray<size_t, 1> outGlobalIndexOnServer = globalIndexSendToServer;
591        CArray<int,1> outLocalIndexToServer = localIndexSendToServer;
592        for (rank = 0; rank < client->serverSize; ++rank)
593        {
594          storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer)));
595          listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
596
597          list_msg.push_back(shared_ptr<CMessage>(new CMessage));
598          *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
599
600          event.push(rank, 1, *list_msg.back());
601        }
602        client->sendEvent(event);
603      }
604      else
605        client->sendEvent(event);
606    }
607    else
608    {
609      std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
610      itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
611      iteGlobalMap = globalIndexOnServer.end();
612
613      int nbGlobalIndex = globalIndexSendToServer.numElements();
614      std::map<int,std::vector<int> >localIndexTmp;
615      std::map<int,std::vector<size_t> > globalIndexTmp;
616      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
617      {
618        int serverRank = itGlobalMap->first;
619        std::vector<size_t>::const_iterator itbVecGlobal = (itGlobalMap->second).begin(),
620                                            iteVecGlobal = (itGlobalMap->second).end();
621        for (int i = 0; i < nbGlobalIndex; ++i)
622        {
623          if (iteVecGlobal != std::find(itbVecGlobal, iteVecGlobal, globalIndexSendToServer(i)))
624          {
625            globalIndexTmp[serverRank].push_back(globalIndexSendToServer(i));
626            localIndexTmp[serverRank].push_back(localIndexSendToServer(i));
627          }
628        }
629      }
630
631      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
632      {
633        rank = connectedServerRank_[ns];
634        int nb = 0;
635        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
636          nb = globalIndexTmp[rank].size();
637
638        CArray<size_t, 1> outGlobalIndexOnServer(nb);
639        CArray<int, 1> outLocalIndexToServer(nb);
640        for (int k = 0; k < nb; ++k)
641        {
642          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
643          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
644        }
645
646        storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer) ));
647        listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
648
649        list_msg.push_back(shared_ptr<CMessage>(new CMessage));
650        *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
651
652        event.push(rank, nbSenders[rank], *list_msg.back());
653      }
654
655      client->sendEvent(event);
656    }
657
658    for(list<CArray<size_t,1>* >::iterator it=listOutIndex.begin();it!=listOutIndex.end();++it) delete *it ;
659  }
660
661  void CGrid::recvIndex(CEventServer& event)
662  {
663    list<CEventServer::SSubEvent>::iterator it ;
664    for (it=event.subEvents.begin();it!=event.subEvents.end();++it)
665    {
666      int rank=it->rank;
667      CBufferIn* buffer=it->buffer;
668      string gridId ;
669      *buffer>>gridId ;
670      get(gridId)->recvIndex(rank,*buffer) ;
671    }
672  }
673
674  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
675                                         const std::vector<CAxis*>& axis,
676                                         const CArray<bool,1>& axisDomainOrder)
677  {
678    globalDim_.resize(domains.size()*2+axis.size());
679    int idx = 0, idxDomain = 0, idxAxis = 0;
680    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
681    {
682      if (axisDomainOrder(i))
683      {
684        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
685        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
686        ++idxDomain;
687        idx += 2;
688      }
689      else
690      {
691        globalDim_[idx] = axis[idxAxis]->size.getValue();
692        ++idxAxis;
693        ++idx;
694      }
695    }
696  }
697
698  std::vector<int> CGrid::getGlobalDimension()
699  {
700    return globalDim_;
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    size_t ssize = 0;
711    for (map<int, CArray<size_t, 1>* >::const_iterator it = outIndexFromClient.begin();
712                                                       it != outIndexFromClient.end(); ++it)
713    {
714      ssize += (it->second)->numElements();
715    }
716    return (0 != ssize);
717  }
718
719  /*!
720    Return size of data which is written on each server
721    Whatever dimension of a grid, data which are written on server must be presented as
722  an one dimension array.
723  \return size of data written on server
724  */
725  size_t CGrid::getWrittenDataSize() const
726  {
727    return writtenDataSize_;
728  }
729
730  const CDistributionServer* CGrid::getDistributionServer() const
731  {
732    return serverDistribution_;
733  }
734
735  bool CGrid::doGridHaveDataDistributed()
736  {
737    if (true == scalar_grid.getValue()) return false;
738    else
739      return isDataDistributed_;
740  }
741
742  void CGrid::recvIndex(int rank, CBufferIn& buffer)
743  {
744    CContext* context = CContext::getCurrent() ;
745    CContextServer* server=context->server ;
746    buffer>>isDataDistributed_;
747    size_t dataSize = 0;
748
749    if (true == scalar_grid)
750    {
751       writtenDataSize_ = 1;
752       CArray<size_t,1> outIndex;
753       buffer>>outIndex;
754       outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
755       std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
756       serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
757                                                     nZoomBeginGlobal, nGlob);
758       return;
759    }
760
761
762     if (0 == serverDistribution_)
763     {
764       int ssize = numElement;
765       std::vector<int> indexMap(numElement);
766       for (int i = 0; i < numElement; ++i)
767       {
768         indexMap[i] = idx;
769         if (true == axis_domain_order(i))
770         {
771            ++ssize;
772            idx += 2;
773         }
774         else
775          ++idx;
776       }
777
778       int axisId = 0, domainId = 0;
779       std::vector<CDomain*> domainList = getDomains();
780       std::vector<CAxis*> axisList = getAxis();
781       std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
782       for (int i = 0; i < numElement; ++i)
783       {
784         if (axis_domain_order(i))
785         {
786            nZoomBegin[indexMap[i]]   = domainList[domainId]->zoom_ibegin_srv;
787            nZoomSize[indexMap[i]]    = domainList[domainId]->zoom_ni_srv;
788            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->zoom_ibegin;
789            nGlob[indexMap[i]]    = domainList[domainId]->ni_glo;
790
791            nZoomBegin[indexMap[i]+1] = domainList[domainId]->zoom_jbegin_srv;
792            nZoomSize[indexMap[i]+1]  = domainList[domainId]->zoom_nj_srv;
793            nZoomBeginGlobal[indexMap[i]+1] = domainList[domainId]->zoom_jbegin;
794            nGlob[indexMap[i]+1]    = domainList[domainId]->nj_glo;
795            ++domainId;
796         }
797         else
798         {
799            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
800            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
801            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->zoom_begin;
802            nGlob[indexMap[i]]      = axisList[axisId]->size;
803            ++axisId;
804         }
805       }
806       dataSize = 1;
807       for (int i = 0; i < nZoomSize.size(); ++i)
808        dataSize *= nZoomSize[i];
809
810       serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
811                                                     nZoomBeginGlobal, nGlob);
812     }
813
814     CArray<size_t,1> outIndex;
815     buffer>>outIndex;
816     if (isDataDistributed_)
817      serverDistribution_->computeLocalIndex(outIndex);
818     else
819     {
820       dataSize = outIndex.numElements();
821       for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
822     }
823     writtenDataSize_ += dataSize;
824
825     outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
826  }
827
828   /*!
829   \brief Dispatch event received from client
830      Whenever a message is received in buffer of server, it will be processed depending on
831   its event type. A new event type should be added in the switch list to make sure
832   it processed on server side.
833   \param [in] event: Received message
834   */
835  bool CGrid::dispatchEvent(CEventServer& event)
836  {
837
838    if (SuperClass::dispatchEvent(event)) return true ;
839    else
840    {
841      switch(event.type)
842      {
843        case EVENT_ID_INDEX :
844          recvIndex(event) ;
845          return true ;
846          break ;
847
848         case EVENT_ID_ADD_DOMAIN :
849           recvAddDomain(event) ;
850           return true ;
851           break ;
852
853         case EVENT_ID_ADD_AXIS :
854           recvAddAxis(event) ;
855           return true ;
856           break ;
857        default :
858          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
859                <<"Unknown Event") ;
860          return false ;
861      }
862    }
863  }
864
865   void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const
866   {
867      if ((this->storeIndex.size()-1 ) != storedClient.size())
868         ERROR("void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const",
869                << "[ Expected received field = " << (this->storeIndex.size()-1) << ", "
870                << "[ received fiedl = "    << storedClient.size() << "] "
871                << "Data from clients are missing!") ;
872      storedServer.resize(storeIndex[0]->numElements());
873
874      for (StdSize i = 0, n = 0; i < storedClient.size(); i++)
875         for (StdSize j = 0; j < storedClient[i]->numElements(); j++)
876            storedServer(n++) = (*storedClient[i])(j);
877   }
878
879   void CGrid::outputFieldToServer(CArray<double,1>& fieldIn, int rank, CArray<double,1>& fieldOut)
880   {
881     CArray<int,1>& index = *storeIndex_toSrv[rank] ;
882     int nb=index.numElements() ;
883     fieldOut.resize(nb) ;
884
885     for(int k=0;k<nb;k++) fieldOut(k)=fieldIn(index(k)) ;
886    }
887   ///---------------------------------------------------------------
888
889   CDomain* CGrid::addDomain(const std::string& id)
890   {
891     return vDomainGroup_->createChild(id) ;
892   }
893
894   CAxis* CGrid::addAxis(const std::string& id)
895   {
896     return vAxisGroup_->createChild(id) ;
897   }
898
899   //! Change virtual field group to a new one
900   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
901   {
902      this->vDomainGroup_ = newVDomainGroup;
903   }
904
905   //! Change virtual variable group to new one
906   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
907   {
908      this->vAxisGroup_ = newVAxisGroup;
909   }
910
911   //----------------------------------------------------------------
912   //! Create virtual field group, which is done normally on initializing file
913   void CGrid::setVirtualDomainGroup(void)
914   {
915      this->setVirtualDomainGroup(CDomainGroup::create());
916   }
917
918   //! Create virtual variable group, which is done normally on initializing file
919   void CGrid::setVirtualAxisGroup(void)
920   {
921      this->setVirtualAxisGroup(CAxisGroup::create());
922   }
923
924   /*!
925   \brief Send a message to create a domain on server side
926   \param[in] id String identity of domain that will be created on server
927   */
928   void CGrid::sendAddDomain(const string& id)
929   {
930    CContext* context=CContext::getCurrent() ;
931
932    if (! context->hasServer )
933    {
934       CContextClient* client=context->client ;
935
936       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN) ;
937       if (client->isServerLeader())
938       {
939         CMessage msg ;
940         msg<<this->getId() ;
941         msg<<id ;
942         event.push(client->getServerLeader(),1,msg) ;
943         client->sendEvent(event) ;
944       }
945       else client->sendEvent(event) ;
946    }
947   }
948
949   /*!
950   \brief Send a message to create an axis on server side
951   \param[in] id String identity of axis that will be created on server
952   */
953   void CGrid::sendAddAxis(const string& id)
954   {
955    CContext* context=CContext::getCurrent() ;
956
957    if (! context->hasServer )
958    {
959       CContextClient* client=context->client ;
960
961       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS) ;
962       if (client->isServerLeader())
963       {
964         CMessage msg ;
965         msg<<this->getId() ;
966         msg<<id ;
967         event.push(client->getServerLeader(),1,msg) ;
968         client->sendEvent(event) ;
969       }
970       else client->sendEvent(event) ;
971    }
972   }
973
974   /*!
975   \brief Receive a message annoucing the creation of a domain on server side
976   \param[in] event Received event
977   */
978   void CGrid::recvAddDomain(CEventServer& event)
979   {
980
981      CBufferIn* buffer=event.subEvents.begin()->buffer;
982      string id;
983      *buffer>>id ;
984      get(id)->recvAddDomain(*buffer) ;
985   }
986
987   /*!
988   \brief Receive a message annoucing the creation of a domain on server side
989   \param[in] buffer Buffer containing message
990   */
991   void CGrid::recvAddDomain(CBufferIn& buffer)
992   {
993      string id ;
994      buffer>>id ;
995      addDomain(id) ;
996   }
997
998   /*!
999   \brief Receive a message annoucing the creation of an axis on server side
1000   \param[in] event Received event
1001   */
1002   void CGrid::recvAddAxis(CEventServer& event)
1003   {
1004
1005      CBufferIn* buffer=event.subEvents.begin()->buffer;
1006      string id;
1007      *buffer>>id ;
1008      get(id)->recvAddAxis(*buffer) ;
1009   }
1010
1011   /*!
1012   \brief Receive a message annoucing the creation of an axis on server side
1013   \param[in] buffer Buffer containing message
1014   */
1015   void CGrid::recvAddAxis(CBufferIn& buffer)
1016   {
1017      string id ;
1018      buffer>>id ;
1019      addAxis(id) ;
1020   }
1021
1022  /*!
1023  \brief Solve domain and axis references
1024  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1025  all attributes from their parents, they should be processed with this function
1026  \param[in] apply inherit all attributes of parents (true)
1027  */
1028  void CGrid::solveDomainAxisRefInheritance(bool apply)
1029  {
1030    CContext* context = CContext::getCurrent();
1031    unsigned int vecSize, i;
1032    std::vector<StdString>::iterator it, itE;
1033    setDomainList();
1034    it = domList_.begin(); itE = domList_.end();
1035    for (; it != itE; ++it)
1036    {
1037      CDomain* pDom = CDomain::get(*it);
1038      if (context->hasClient)
1039      {
1040        pDom->solveRefInheritance(apply);
1041        pDom->solveBaseReference();
1042        if ((!pDom->domain_ref.isEmpty()) && (pDom->name.isEmpty()))
1043          pDom->name.setValue(pDom->getBaseDomainReference()->getId());
1044      }
1045    }
1046
1047    setAxisList();
1048    it = axisList_.begin(); itE = axisList_.end();
1049    for (; it != itE; ++it)
1050    {
1051      CAxis* pAxis = CAxis::get(*it);
1052      if (context->hasClient)
1053      {
1054        pAxis->solveRefInheritance(apply);
1055        pAxis->solveBaseReference();
1056        if ((!pAxis->axis_ref.isEmpty()) && (pAxis->name.isEmpty()))
1057          pAxis->name.setValue(pAxis->getBaseAxisReference()->getId());
1058      }
1059    }
1060  }
1061
1062  /*!
1063  \brief Get the list of domain pointers
1064  \return list of domain pointers
1065  */
1066  std::vector<CDomain*> CGrid::getDomains()
1067  {
1068    std::vector<CDomain*> domList;
1069    if (!domList_.empty())
1070    {
1071      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1072    }
1073    return domList;
1074  }
1075
1076  /*!
1077  \brief Get the list of  axis pointers
1078  \return list of axis pointers
1079  */
1080  std::vector<CAxis*> CGrid::getAxis()
1081  {
1082    std::vector<CAxis*> aList;
1083    if (!axisList_.empty())
1084      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1085
1086    return aList;
1087  }
1088
1089  /*!
1090  \brief Set domain(s) of a grid from a list
1091  \param[in] domains list of domains
1092  */
1093  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1094  {
1095    if (isDomListSet) return;
1096    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1097    if (!domains.empty() && domList.empty()) domList = domains;
1098    if (!domList.empty())
1099    {
1100      int sizeDom = domList.size();
1101      domList_.resize(sizeDom);
1102      for (int i = 0 ; i < sizeDom; ++i)
1103      {
1104        domList_[i] = domList[i]->getId();
1105      }
1106      isDomListSet = true;
1107    }
1108
1109  }
1110
1111  /*!
1112  \brief Set axis(s) of a grid from a list
1113  \param[in] axis list of axis
1114  */
1115  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1116  {
1117    if (isAxisListSet) return;
1118    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1119    if (!axis.empty() && aList.empty()) aList = axis;
1120    if (!aList.empty())
1121    {
1122      int sizeAxis = aList.size();
1123      axisList_.resize(sizeAxis);
1124      for (int i = 0; i < sizeAxis; ++i)
1125      {
1126        axisList_[i] = aList[i]->getId();
1127      }
1128      isAxisListSet = true;
1129    }
1130  }
1131
1132  /*!
1133  \brief Get list of id of domains
1134  \return id list of domains
1135  */
1136  std::vector<StdString> CGrid::getDomainList()
1137  {
1138    setDomainList();
1139    return domList_;
1140  }
1141
1142  /*!
1143  \brief Get list of id of axis
1144  \return id list of axis
1145  */
1146  std::vector<StdString> CGrid::getAxisList()
1147  {
1148    setAxisList();
1149    return axisList_;
1150  }
1151
1152  void CGrid::sendAllDomains()
1153  {
1154    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1155    int dSize = domList.size();
1156    for (int i = 0; i < dSize; ++i)
1157    {
1158      sendAddDomain(domList[i]->getId());
1159      domList[i]->sendAllAttributesToServer();
1160    }
1161  }
1162
1163  void CGrid::sendAllAxis()
1164  {
1165    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1166    int aSize = aList.size();
1167
1168    for (int i = 0; i < aSize; ++i)
1169    {
1170      sendAddAxis(aList[i]->getId());
1171      aList[i]->sendAllAttributesToServer();
1172    }
1173  }
1174
1175  void CGrid::parse(xml::CXMLNode & node)
1176  {
1177    SuperClass::parse(node);
1178
1179    // List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false)
1180    std::vector<bool> order;
1181
1182    if (node.goToChildElement())
1183    {
1184      StdString domainName("domain");
1185      StdString axisName("axis");
1186      do
1187      {
1188        if (node.getElementName() == domainName) {
1189          order.push_back(true);
1190          this->getVirtualDomainGroup()->parseChild(node);
1191        }
1192        if (node.getElementName() == axisName) {
1193          order.push_back(false);
1194          this->getVirtualAxisGroup()->parseChild(node);
1195        }
1196      } while (node.goToNextElement()) ;
1197      node.goToParentElement();
1198    }
1199
1200    if (!order.empty())
1201    {
1202      int sizeOrd = order.size();
1203      axis_domain_order.resize(sizeOrd);
1204      for (int i = 0; i < sizeOrd; ++i)
1205      {
1206        axis_domain_order(i) = order[i];
1207      }
1208      scalar_grid = false;
1209    }
1210    else scalar_grid = true;
1211
1212    setDomainList();
1213    setAxisList();
1214   }
1215
1216} // namespace xios
Note: See TracBrowser for help on using the repository browser.