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

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

Add a new interface xios_recv_field to get local instant data from a field.

  • 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.8 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         event.push(client->getServerLeader(),1,msg) ;
952         client->sendEvent(event) ;
953       }
954       else client->sendEvent(event) ;
955    }
956   }
957
958   /*!
959   \brief Send a message to create an axis on server side
960   \param[in] id String identity of axis that will be created on server
961   */
962   void CGrid::sendAddAxis(const string& id)
963   {
964    CContext* context=CContext::getCurrent() ;
965
966    if (! context->hasServer )
967    {
968       CContextClient* client=context->client ;
969
970       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS) ;
971       if (client->isServerLeader())
972       {
973         CMessage msg ;
974         msg<<this->getId() ;
975         msg<<id ;
976         event.push(client->getServerLeader(),1,msg) ;
977         client->sendEvent(event) ;
978       }
979       else client->sendEvent(event) ;
980    }
981   }
982
983   /*!
984   \brief Receive a message annoucing the creation of a domain on server side
985   \param[in] event Received event
986   */
987   void CGrid::recvAddDomain(CEventServer& event)
988   {
989
990      CBufferIn* buffer=event.subEvents.begin()->buffer;
991      string id;
992      *buffer>>id ;
993      get(id)->recvAddDomain(*buffer) ;
994   }
995
996   /*!
997   \brief Receive a message annoucing the creation of a domain on server side
998   \param[in] buffer Buffer containing message
999   */
1000   void CGrid::recvAddDomain(CBufferIn& buffer)
1001   {
1002      string id ;
1003      buffer>>id ;
1004      addDomain(id) ;
1005   }
1006
1007   /*!
1008   \brief Receive a message annoucing the creation of an axis on server side
1009   \param[in] event Received event
1010   */
1011   void CGrid::recvAddAxis(CEventServer& event)
1012   {
1013
1014      CBufferIn* buffer=event.subEvents.begin()->buffer;
1015      string id;
1016      *buffer>>id ;
1017      get(id)->recvAddAxis(*buffer) ;
1018   }
1019
1020   /*!
1021   \brief Receive a message annoucing the creation of an axis on server side
1022   \param[in] buffer Buffer containing message
1023   */
1024   void CGrid::recvAddAxis(CBufferIn& buffer)
1025   {
1026      string id ;
1027      buffer>>id ;
1028      addAxis(id) ;
1029   }
1030
1031  /*!
1032  \brief Solve domain and axis references
1033  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1034  all attributes from their parents, they should be processed with this function
1035  \param[in] apply inherit all attributes of parents (true)
1036  */
1037  void CGrid::solveDomainAxisRefInheritance(bool apply)
1038  {
1039    CContext* context = CContext::getCurrent();
1040    unsigned int vecSize, i;
1041    std::vector<StdString>::iterator it, itE;
1042    setDomainList();
1043    it = domList_.begin(); itE = domList_.end();
1044    for (; it != itE; ++it)
1045    {
1046      CDomain* pDom = CDomain::get(*it);
1047      if (context->hasClient)
1048      {
1049        pDom->solveRefInheritance(apply);
1050        pDom->solveBaseReference();
1051        if ((!pDom->domain_ref.isEmpty()) && (pDom->name.isEmpty()))
1052          pDom->name.setValue(pDom->getBaseDomainReference()->getId());
1053      }
1054    }
1055
1056    setAxisList();
1057    it = axisList_.begin(); itE = axisList_.end();
1058    for (; it != itE; ++it)
1059    {
1060      CAxis* pAxis = CAxis::get(*it);
1061      if (context->hasClient)
1062      {
1063        pAxis->solveRefInheritance(apply);
1064        pAxis->solveBaseReference();
1065        if ((!pAxis->axis_ref.isEmpty()) && (pAxis->name.isEmpty()))
1066          pAxis->name.setValue(pAxis->getBaseAxisReference()->getId());
1067      }
1068    }
1069  }
1070
1071  /*!
1072  \brief Get the list of domain pointers
1073  \return list of domain pointers
1074  */
1075  std::vector<CDomain*> CGrid::getDomains()
1076  {
1077    std::vector<CDomain*> domList;
1078    if (!domList_.empty())
1079    {
1080      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1081    }
1082    return domList;
1083  }
1084
1085  /*!
1086  \brief Get the list of  axis pointers
1087  \return list of axis pointers
1088  */
1089  std::vector<CAxis*> CGrid::getAxis()
1090  {
1091    std::vector<CAxis*> aList;
1092    if (!axisList_.empty())
1093      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1094
1095    return aList;
1096  }
1097
1098  /*!
1099  \brief Set domain(s) of a grid from a list
1100  \param[in] domains list of domains
1101  */
1102  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1103  {
1104    if (isDomListSet) return;
1105    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1106    if (!domains.empty() && domList.empty()) domList = domains;
1107    if (!domList.empty())
1108    {
1109      int sizeDom = domList.size();
1110      domList_.resize(sizeDom);
1111      for (int i = 0 ; i < sizeDom; ++i)
1112      {
1113        domList_[i] = domList[i]->getId();
1114      }
1115      isDomListSet = true;
1116    }
1117
1118  }
1119
1120  /*!
1121  \brief Set axis(s) of a grid from a list
1122  \param[in] axis list of axis
1123  */
1124  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1125  {
1126    if (isAxisListSet) return;
1127    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1128    if (!axis.empty() && aList.empty()) aList = axis;
1129    if (!aList.empty())
1130    {
1131      int sizeAxis = aList.size();
1132      axisList_.resize(sizeAxis);
1133      for (int i = 0; i < sizeAxis; ++i)
1134      {
1135        axisList_[i] = aList[i]->getId();
1136      }
1137      isAxisListSet = true;
1138    }
1139  }
1140
1141  /*!
1142  \brief Get list of id of domains
1143  \return id list of domains
1144  */
1145  std::vector<StdString> CGrid::getDomainList()
1146  {
1147    setDomainList();
1148    return domList_;
1149  }
1150
1151  /*!
1152  \brief Get list of id of axis
1153  \return id list of axis
1154  */
1155  std::vector<StdString> CGrid::getAxisList()
1156  {
1157    setAxisList();
1158    return axisList_;
1159  }
1160
1161  void CGrid::sendAllDomains()
1162  {
1163    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1164    int dSize = domList.size();
1165    for (int i = 0; i < dSize; ++i)
1166    {
1167      sendAddDomain(domList[i]->getId());
1168      domList[i]->sendAllAttributesToServer();
1169    }
1170  }
1171
1172  void CGrid::sendAllAxis()
1173  {
1174    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1175    int aSize = aList.size();
1176
1177    for (int i = 0; i < aSize; ++i)
1178    {
1179      sendAddAxis(aList[i]->getId());
1180      aList[i]->sendAllAttributesToServer();
1181    }
1182  }
1183
1184  void CGrid::parse(xml::CXMLNode & node)
1185  {
1186    SuperClass::parse(node);
1187
1188    // List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false)
1189    std::vector<bool> order;
1190
1191    if (node.goToChildElement())
1192    {
1193      StdString domainName("domain");
1194      StdString axisName("axis");
1195      do
1196      {
1197        if (node.getElementName() == domainName) {
1198          order.push_back(true);
1199          this->getVirtualDomainGroup()->parseChild(node);
1200        }
1201        if (node.getElementName() == axisName) {
1202          order.push_back(false);
1203          this->getVirtualAxisGroup()->parseChild(node);
1204        }
1205      } while (node.goToNextElement()) ;
1206      node.goToParentElement();
1207    }
1208
1209    if (!order.empty())
1210    {
1211      int sizeOrd = order.size();
1212      axis_domain_order.resize(sizeOrd);
1213      for (int i = 0; i < sizeOrd; ++i)
1214      {
1215        axis_domain_order(i) = order[i];
1216      }
1217      scalar_grid = false;
1218    }
1219    else scalar_grid = true;
1220
1221    setDomainList();
1222    setAxisList();
1223   }
1224
1225} // namespace xios
Note: See TracBrowser for help on using the repository browser.