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

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

Fix: The computed size of the field data was off by one.

The problem caused no crash thanks to the safety coefficient applied when computing the buffer sizes.

  • 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.6 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] = 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::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 idx = 0, numElement = axis_domain_order.numElements();
765       int ssize = numElement;
766       std::vector<int> indexMap(numElement);
767       for (int i = 0; i < numElement; ++i)
768       {
769         indexMap[i] = idx;
770         if (true == axis_domain_order(i))
771         {
772            ++ssize;
773            idx += 2;
774         }
775         else
776          ++idx;
777       }
778
779       int axisId = 0, domainId = 0;
780       std::vector<CDomain*> domainList = getDomains();
781       std::vector<CAxis*> axisList = getAxis();
782       std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
783       for (int i = 0; i < numElement; ++i)
784       {
785         if (axis_domain_order(i))
786         {
787            nZoomBegin[indexMap[i]]   = domainList[domainId]->zoom_ibegin_srv;
788            nZoomSize[indexMap[i]]    = domainList[domainId]->zoom_ni_srv;
789            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->zoom_ibegin;
790            nGlob[indexMap[i]]    = domainList[domainId]->ni_glo;
791
792            nZoomBegin[indexMap[i]+1] = domainList[domainId]->zoom_jbegin_srv;
793            nZoomSize[indexMap[i]+1]  = domainList[domainId]->zoom_nj_srv;
794            nZoomBeginGlobal[indexMap[i]+1] = domainList[domainId]->zoom_jbegin;
795            nGlob[indexMap[i]+1]    = domainList[domainId]->nj_glo;
796            ++domainId;
797         }
798         else
799         {
800            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
801            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
802            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->zoom_begin;
803            nGlob[indexMap[i]]      = axisList[axisId]->size;
804            ++axisId;
805         }
806       }
807       dataSize = 1;
808       for (int i = 0; i < nZoomSize.size(); ++i)
809        dataSize *= nZoomSize[i];
810
811       serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
812                                                     nZoomBeginGlobal, nGlob);
813     }
814
815     CArray<size_t,1> outIndex;
816     buffer>>outIndex;
817     if (isDataDistributed_)
818      serverDistribution_->computeLocalIndex(outIndex);
819     else
820     {
821       dataSize = outIndex.numElements();
822       for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
823     }
824     writtenDataSize_ += dataSize;
825
826     outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
827  }
828
829   /*!
830   \brief Dispatch event received from client
831      Whenever a message is received in buffer of server, it will be processed depending on
832   its event type. A new event type should be added in the switch list to make sure
833   it processed on server side.
834   \param [in] event: Received message
835   */
836  bool CGrid::dispatchEvent(CEventServer& event)
837  {
838
839    if (SuperClass::dispatchEvent(event)) return true ;
840    else
841    {
842      switch(event.type)
843      {
844        case EVENT_ID_INDEX :
845          recvIndex(event) ;
846          return true ;
847          break ;
848
849         case EVENT_ID_ADD_DOMAIN :
850           recvAddDomain(event) ;
851           return true ;
852           break ;
853
854         case EVENT_ID_ADD_AXIS :
855           recvAddAxis(event) ;
856           return true ;
857           break ;
858        default :
859          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
860                <<"Unknown Event") ;
861          return false ;
862      }
863    }
864  }
865
866   void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const
867   {
868      if ((this->storeIndex.size()-1 ) != storedClient.size())
869         ERROR("void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const",
870                << "[ Expected received field = " << (this->storeIndex.size()-1) << ", "
871                << "[ received fiedl = "    << storedClient.size() << "] "
872                << "Data from clients are missing!") ;
873      storedServer.resize(storeIndex[0]->numElements());
874
875      for (StdSize i = 0, n = 0; i < storedClient.size(); i++)
876         for (StdSize j = 0; j < storedClient[i]->numElements(); j++)
877            storedServer(n++) = (*storedClient[i])(j);
878   }
879
880   void CGrid::outputFieldToServer(CArray<double,1>& fieldIn, int rank, CArray<double,1>& fieldOut)
881   {
882     CArray<int,1>& index = *storeIndex_toSrv[rank] ;
883     int nb=index.numElements() ;
884     fieldOut.resize(nb) ;
885
886     for(int k=0;k<nb;k++) fieldOut(k)=fieldIn(index(k)) ;
887    }
888   ///---------------------------------------------------------------
889
890   CDomain* CGrid::addDomain(const std::string& id)
891   {
892     return vDomainGroup_->createChild(id) ;
893   }
894
895   CAxis* CGrid::addAxis(const std::string& id)
896   {
897     return vAxisGroup_->createChild(id) ;
898   }
899
900   //! Change virtual field group to a new one
901   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
902   {
903      this->vDomainGroup_ = newVDomainGroup;
904   }
905
906   //! Change virtual variable group to new one
907   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
908   {
909      this->vAxisGroup_ = newVAxisGroup;
910   }
911
912   //----------------------------------------------------------------
913   //! Create virtual field group, which is done normally on initializing file
914   void CGrid::setVirtualDomainGroup(void)
915   {
916      this->setVirtualDomainGroup(CDomainGroup::create());
917   }
918
919   //! Create virtual variable group, which is done normally on initializing file
920   void CGrid::setVirtualAxisGroup(void)
921   {
922      this->setVirtualAxisGroup(CAxisGroup::create());
923   }
924
925   /*!
926   \brief Send a message to create a domain on server side
927   \param[in] id String identity of domain that will be created on server
928   */
929   void CGrid::sendAddDomain(const string& id)
930   {
931    CContext* context=CContext::getCurrent() ;
932
933    if (! context->hasServer )
934    {
935       CContextClient* client=context->client ;
936
937       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN) ;
938       if (client->isServerLeader())
939       {
940         CMessage msg ;
941         msg<<this->getId() ;
942         msg<<id ;
943         event.push(client->getServerLeader(),1,msg) ;
944         client->sendEvent(event) ;
945       }
946       else client->sendEvent(event) ;
947    }
948   }
949
950   /*!
951   \brief Send a message to create an axis on server side
952   \param[in] id String identity of axis that will be created on server
953   */
954   void CGrid::sendAddAxis(const string& id)
955   {
956    CContext* context=CContext::getCurrent() ;
957
958    if (! context->hasServer )
959    {
960       CContextClient* client=context->client ;
961
962       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS) ;
963       if (client->isServerLeader())
964       {
965         CMessage msg ;
966         msg<<this->getId() ;
967         msg<<id ;
968         event.push(client->getServerLeader(),1,msg) ;
969         client->sendEvent(event) ;
970       }
971       else client->sendEvent(event) ;
972    }
973   }
974
975   /*!
976   \brief Receive a message annoucing the creation of a domain on server side
977   \param[in] event Received event
978   */
979   void CGrid::recvAddDomain(CEventServer& event)
980   {
981
982      CBufferIn* buffer=event.subEvents.begin()->buffer;
983      string id;
984      *buffer>>id ;
985      get(id)->recvAddDomain(*buffer) ;
986   }
987
988   /*!
989   \brief Receive a message annoucing the creation of a domain on server side
990   \param[in] buffer Buffer containing message
991   */
992   void CGrid::recvAddDomain(CBufferIn& buffer)
993   {
994      string id ;
995      buffer>>id ;
996      addDomain(id) ;
997   }
998
999   /*!
1000   \brief Receive a message annoucing the creation of an axis on server side
1001   \param[in] event Received event
1002   */
1003   void CGrid::recvAddAxis(CEventServer& event)
1004   {
1005
1006      CBufferIn* buffer=event.subEvents.begin()->buffer;
1007      string id;
1008      *buffer>>id ;
1009      get(id)->recvAddAxis(*buffer) ;
1010   }
1011
1012   /*!
1013   \brief Receive a message annoucing the creation of an axis on server side
1014   \param[in] buffer Buffer containing message
1015   */
1016   void CGrid::recvAddAxis(CBufferIn& buffer)
1017   {
1018      string id ;
1019      buffer>>id ;
1020      addAxis(id) ;
1021   }
1022
1023  /*!
1024  \brief Solve domain and axis references
1025  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1026  all attributes from their parents, they should be processed with this function
1027  \param[in] apply inherit all attributes of parents (true)
1028  */
1029  void CGrid::solveDomainAxisRefInheritance(bool apply)
1030  {
1031    CContext* context = CContext::getCurrent();
1032    unsigned int vecSize, i;
1033    std::vector<StdString>::iterator it, itE;
1034    setDomainList();
1035    it = domList_.begin(); itE = domList_.end();
1036    for (; it != itE; ++it)
1037    {
1038      CDomain* pDom = CDomain::get(*it);
1039      if (context->hasClient)
1040      {
1041        pDom->solveRefInheritance(apply);
1042        pDom->solveBaseReference();
1043        if ((!pDom->domain_ref.isEmpty()) && (pDom->name.isEmpty()))
1044          pDom->name.setValue(pDom->getBaseDomainReference()->getId());
1045      }
1046    }
1047
1048    setAxisList();
1049    it = axisList_.begin(); itE = axisList_.end();
1050    for (; it != itE; ++it)
1051    {
1052      CAxis* pAxis = CAxis::get(*it);
1053      if (context->hasClient)
1054      {
1055        pAxis->solveRefInheritance(apply);
1056        pAxis->solveBaseReference();
1057        if ((!pAxis->axis_ref.isEmpty()) && (pAxis->name.isEmpty()))
1058          pAxis->name.setValue(pAxis->getBaseAxisReference()->getId());
1059      }
1060    }
1061  }
1062
1063  /*!
1064  \brief Get the list of domain pointers
1065  \return list of domain pointers
1066  */
1067  std::vector<CDomain*> CGrid::getDomains()
1068  {
1069    std::vector<CDomain*> domList;
1070    if (!domList_.empty())
1071    {
1072      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1073    }
1074    return domList;
1075  }
1076
1077  /*!
1078  \brief Get the list of  axis pointers
1079  \return list of axis pointers
1080  */
1081  std::vector<CAxis*> CGrid::getAxis()
1082  {
1083    std::vector<CAxis*> aList;
1084    if (!axisList_.empty())
1085      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1086
1087    return aList;
1088  }
1089
1090  /*!
1091  \brief Set domain(s) of a grid from a list
1092  \param[in] domains list of domains
1093  */
1094  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1095  {
1096    if (isDomListSet) return;
1097    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1098    if (!domains.empty() && domList.empty()) domList = domains;
1099    if (!domList.empty())
1100    {
1101      int sizeDom = domList.size();
1102      domList_.resize(sizeDom);
1103      for (int i = 0 ; i < sizeDom; ++i)
1104      {
1105        domList_[i] = domList[i]->getId();
1106      }
1107      isDomListSet = true;
1108    }
1109
1110  }
1111
1112  /*!
1113  \brief Set axis(s) of a grid from a list
1114  \param[in] axis list of axis
1115  */
1116  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1117  {
1118    if (isAxisListSet) return;
1119    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1120    if (!axis.empty() && aList.empty()) aList = axis;
1121    if (!aList.empty())
1122    {
1123      int sizeAxis = aList.size();
1124      axisList_.resize(sizeAxis);
1125      for (int i = 0; i < sizeAxis; ++i)
1126      {
1127        axisList_[i] = aList[i]->getId();
1128      }
1129      isAxisListSet = true;
1130    }
1131  }
1132
1133  /*!
1134  \brief Get list of id of domains
1135  \return id list of domains
1136  */
1137  std::vector<StdString> CGrid::getDomainList()
1138  {
1139    setDomainList();
1140    return domList_;
1141  }
1142
1143  /*!
1144  \brief Get list of id of axis
1145  \return id list of axis
1146  */
1147  std::vector<StdString> CGrid::getAxisList()
1148  {
1149    setAxisList();
1150    return axisList_;
1151  }
1152
1153  void CGrid::sendAllDomains()
1154  {
1155    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1156    int dSize = domList.size();
1157    for (int i = 0; i < dSize; ++i)
1158    {
1159      sendAddDomain(domList[i]->getId());
1160      domList[i]->sendAllAttributesToServer();
1161    }
1162  }
1163
1164  void CGrid::sendAllAxis()
1165  {
1166    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1167    int aSize = aList.size();
1168
1169    for (int i = 0; i < aSize; ++i)
1170    {
1171      sendAddAxis(aList[i]->getId());
1172      aList[i]->sendAllAttributesToServer();
1173    }
1174  }
1175
1176  void CGrid::parse(xml::CXMLNode & node)
1177  {
1178    SuperClass::parse(node);
1179
1180    // List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false)
1181    std::vector<bool> order;
1182
1183    if (node.goToChildElement())
1184    {
1185      StdString domainName("domain");
1186      StdString axisName("axis");
1187      do
1188      {
1189        if (node.getElementName() == domainName) {
1190          order.push_back(true);
1191          this->getVirtualDomainGroup()->parseChild(node);
1192        }
1193        if (node.getElementName() == axisName) {
1194          order.push_back(false);
1195          this->getVirtualAxisGroup()->parseChild(node);
1196        }
1197      } while (node.goToNextElement()) ;
1198      node.goToParentElement();
1199    }
1200
1201    if (!order.empty())
1202    {
1203      int sizeOrd = order.size();
1204      axis_domain_order.resize(sizeOrd);
1205      for (int i = 0; i < sizeOrd; ++i)
1206      {
1207        axis_domain_order(i) = order[i];
1208      }
1209      scalar_grid = false;
1210    }
1211    else scalar_grid = true;
1212
1213    setDomainList();
1214    setAxisList();
1215   }
1216
1217} // namespace xios
Note: See TracBrowser for help on using the repository browser.