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

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

Add the infrastructure to request fields from the server.

This will be used to read input files so add a new file attribute mode to define whether data is written or read from a file.

Currently the data is not actually read and random data is transfered for those fields in read mode.

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 38.7 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    string gridId;
672    vector<int> ranks;
673    vector<CBufferIn*> buffers;
674
675    list<CEventServer::SSubEvent>::iterator it;
676    for (it=event.subEvents.begin();it!=event.subEvents.end();++it)
677    {
678      ranks.push_back(it->rank);
679      CBufferIn* buffer = it->buffer;
680      *buffer >> gridId;
681      buffers.push_back(buffer);
682    }
683    get(gridId)->recvIndex(ranks, buffers) ;
684  }
685
686  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
687                                         const std::vector<CAxis*>& axis,
688                                         const CArray<bool,1>& axisDomainOrder)
689  {
690    globalDim_.resize(domains.size()*2+axis.size());
691    int idx = 0, idxDomain = 0, idxAxis = 0;
692    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
693    {
694      if (axisDomainOrder(i))
695      {
696        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
697        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
698        ++idxDomain;
699        idx += 2;
700      }
701      else
702      {
703        globalDim_[idx] = axis[idxAxis]->size.getValue();
704        ++idxAxis;
705        ++idx;
706      }
707    }
708  }
709
710  std::vector<int> CGrid::getGlobalDimension()
711  {
712    return globalDim_;
713  }
714
715  /*!
716    Verify whether one server need to write data
717    There are some cases on which one server has nodata to write. For example, when we
718  just only want to zoom on a domain.
719  */
720  bool CGrid::doGridHaveDataToWrite()
721  {
722    size_t ssize = 0;
723    for (map<int, CArray<size_t, 1>* >::const_iterator it = outIndexFromClient.begin();
724                                                       it != outIndexFromClient.end(); ++it)
725    {
726      ssize += (it->second)->numElements();
727    }
728    return (0 != ssize);
729  }
730
731  /*!
732    Return size of data which is written on each server
733    Whatever dimension of a grid, data which are written on server must be presented as
734  an one dimension array.
735  \return size of data written on server
736  */
737  size_t CGrid::getWrittenDataSize() const
738  {
739    return writtenDataSize_;
740  }
741
742  const CDistributionServer* CGrid::getDistributionServer() const
743  {
744    return serverDistribution_;
745  }
746
747  bool CGrid::doGridHaveDataDistributed()
748  {
749    if (true == scalar_grid.getValue()) return false;
750    else
751      return isDataDistributed_;
752  }
753
754  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
755  {
756    CContext* context = CContext::getCurrent();
757    CContextServer* server = context->server;
758
759    for (int n = 0; n < ranks.size(); n++)
760    {
761      int rank = ranks[n];
762      CBufferIn& buffer = *buffers[n];
763
764      buffer >> isDataDistributed_;
765      size_t dataSize = 0;
766
767      if (true == scalar_grid)
768      {
769        writtenDataSize_ = 1;
770        CArray<size_t,1> outIndex;
771        buffer >> outIndex;
772        outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
773        std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
774        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
775                                                      nZoomBeginGlobal, nGlob);
776        return;
777      }
778
779      if (0 == serverDistribution_)
780      {
781        int idx = 0, numElement = axis_domain_order.numElements();
782        int ssize = numElement;
783        std::vector<int> indexMap(numElement);
784        for (int i = 0; i < numElement; ++i)
785        {
786          indexMap[i] = idx;
787          if (true == axis_domain_order(i))
788          {
789            ++ssize;
790            idx += 2;
791          }
792          else
793            ++idx;
794        }
795
796        int axisId = 0, domainId = 0;
797        std::vector<CDomain*> domainList = getDomains();
798        std::vector<CAxis*> axisList = getAxis();
799        std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
800        for (int i = 0; i < numElement; ++i)
801        {
802          if (axis_domain_order(i))
803          {
804            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
805            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
806            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->zoom_ibegin;
807            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
808
809            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
810            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
811            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin;
812            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
813            ++domainId;
814          }
815          else
816          {
817            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
818            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
819            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->zoom_begin;
820            nGlob[indexMap[i]] = axisList[axisId]->size;
821            ++axisId;
822          }
823        }
824        dataSize = 1;
825        for (int i = 0; i < nZoomSize.size(); ++i)
826          dataSize *= nZoomSize[i];
827
828        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
829                                                      nZoomBeginGlobal, nGlob);
830      }
831
832      CArray<size_t,1> outIndex;
833      buffer >> outIndex;
834      if (isDataDistributed_)
835        serverDistribution_->computeLocalIndex(outIndex);
836      else
837      {
838        dataSize = outIndex.numElements();
839        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
840      }
841      writtenDataSize_ += dataSize;
842
843      outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
844      connectedDataSize_[rank] = outIndex.numElements();
845    }
846
847    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
848  }
849
850   /*!
851   \brief Dispatch event received from client
852      Whenever a message is received in buffer of server, it will be processed depending on
853   its event type. A new event type should be added in the switch list to make sure
854   it processed on server side.
855   \param [in] event: Received message
856   */
857  bool CGrid::dispatchEvent(CEventServer& event)
858  {
859
860    if (SuperClass::dispatchEvent(event)) return true ;
861    else
862    {
863      switch(event.type)
864      {
865        case EVENT_ID_INDEX :
866          recvIndex(event) ;
867          return true ;
868          break ;
869
870         case EVENT_ID_ADD_DOMAIN :
871           recvAddDomain(event) ;
872           return true ;
873           break ;
874
875         case EVENT_ID_ADD_AXIS :
876           recvAddAxis(event) ;
877           return true ;
878           break ;
879        default :
880          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
881                <<"Unknown Event") ;
882          return false ;
883      }
884    }
885  }
886
887   void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const
888   {
889      if ((this->storeIndex.size()-1 ) != storedClient.size())
890         ERROR("void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const",
891                << "[ Expected received field = " << (this->storeIndex.size()-1) << ", "
892                << "[ received fiedl = "    << storedClient.size() << "] "
893                << "Data from clients are missing!") ;
894      storedServer.resize(storeIndex[0]->numElements());
895
896      for (StdSize i = 0, n = 0; i < storedClient.size(); i++)
897         for (StdSize j = 0; j < storedClient[i]->numElements(); j++)
898            storedServer(n++) = (*storedClient[i])(j);
899   }
900
901   void CGrid::outputFieldToServer(CArray<double,1>& fieldIn, int rank, CArray<double,1>& fieldOut)
902   {
903     CArray<int,1>& index = *storeIndex_toSrv[rank] ;
904     int nb=index.numElements() ;
905     fieldOut.resize(nb) ;
906
907     for(int k=0;k<nb;k++) fieldOut(k)=fieldIn(index(k)) ;
908    }
909   ///---------------------------------------------------------------
910
911   CDomain* CGrid::addDomain(const std::string& id)
912   {
913     return vDomainGroup_->createChild(id) ;
914   }
915
916   CAxis* CGrid::addAxis(const std::string& id)
917   {
918     return vAxisGroup_->createChild(id) ;
919   }
920
921   //! Change virtual field group to a new one
922   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
923   {
924      this->vDomainGroup_ = newVDomainGroup;
925   }
926
927   //! Change virtual variable group to new one
928   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
929   {
930      this->vAxisGroup_ = newVAxisGroup;
931   }
932
933   //----------------------------------------------------------------
934   //! Create virtual field group, which is done normally on initializing file
935   void CGrid::setVirtualDomainGroup(void)
936   {
937      this->setVirtualDomainGroup(CDomainGroup::create());
938   }
939
940   //! Create virtual variable group, which is done normally on initializing file
941   void CGrid::setVirtualAxisGroup(void)
942   {
943      this->setVirtualAxisGroup(CAxisGroup::create());
944   }
945
946   /*!
947   \brief Send a message to create a domain on server side
948   \param[in] id String identity of domain that will be created on server
949   */
950   void CGrid::sendAddDomain(const string& id)
951   {
952    CContext* context=CContext::getCurrent() ;
953
954    if (! context->hasServer )
955    {
956       CContextClient* client=context->client ;
957
958       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN) ;
959       if (client->isServerLeader())
960       {
961         CMessage msg ;
962         msg<<this->getId() ;
963         msg<<id ;
964         const std::list<int>& ranks = client->getRanksServerLeader();
965         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
966           event.push(*itRank,1,msg);
967         client->sendEvent(event) ;
968       }
969       else client->sendEvent(event) ;
970    }
971   }
972
973   /*!
974   \brief Send a message to create an axis on server side
975   \param[in] id String identity of axis that will be created on server
976   */
977   void CGrid::sendAddAxis(const string& id)
978   {
979    CContext* context=CContext::getCurrent() ;
980
981    if (! context->hasServer )
982    {
983       CContextClient* client=context->client ;
984
985       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS) ;
986       if (client->isServerLeader())
987       {
988         CMessage msg ;
989         msg<<this->getId() ;
990         msg<<id ;
991         const std::list<int>& ranks = client->getRanksServerLeader();
992         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
993           event.push(*itRank,1,msg);
994         client->sendEvent(event) ;
995       }
996       else client->sendEvent(event) ;
997    }
998   }
999
1000   /*!
1001   \brief Receive a message annoucing the creation of a domain on server side
1002   \param[in] event Received event
1003   */
1004   void CGrid::recvAddDomain(CEventServer& event)
1005   {
1006
1007      CBufferIn* buffer=event.subEvents.begin()->buffer;
1008      string id;
1009      *buffer>>id ;
1010      get(id)->recvAddDomain(*buffer) ;
1011   }
1012
1013   /*!
1014   \brief Receive a message annoucing the creation of a domain on server side
1015   \param[in] buffer Buffer containing message
1016   */
1017   void CGrid::recvAddDomain(CBufferIn& buffer)
1018   {
1019      string id ;
1020      buffer>>id ;
1021      addDomain(id) ;
1022   }
1023
1024   /*!
1025   \brief Receive a message annoucing the creation of an axis on server side
1026   \param[in] event Received event
1027   */
1028   void CGrid::recvAddAxis(CEventServer& event)
1029   {
1030
1031      CBufferIn* buffer=event.subEvents.begin()->buffer;
1032      string id;
1033      *buffer>>id ;
1034      get(id)->recvAddAxis(*buffer) ;
1035   }
1036
1037   /*!
1038   \brief Receive a message annoucing the creation of an axis on server side
1039   \param[in] buffer Buffer containing message
1040   */
1041   void CGrid::recvAddAxis(CBufferIn& buffer)
1042   {
1043      string id ;
1044      buffer>>id ;
1045      addAxis(id) ;
1046   }
1047
1048  /*!
1049  \brief Solve domain and axis references
1050  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1051  all attributes from their parents, they should be processed with this function
1052  \param[in] apply inherit all attributes of parents (true)
1053  */
1054  void CGrid::solveDomainAxisRefInheritance(bool apply)
1055  {
1056    CContext* context = CContext::getCurrent();
1057    unsigned int vecSize, i;
1058    std::vector<StdString>::iterator it, itE;
1059    setDomainList();
1060    it = domList_.begin(); itE = domList_.end();
1061    for (; it != itE; ++it)
1062    {
1063      CDomain* pDom = CDomain::get(*it);
1064      if (context->hasClient)
1065      {
1066        pDom->solveRefInheritance(apply);
1067        pDom->solveBaseReference();
1068        if ((!pDom->domain_ref.isEmpty()) && (pDom->name.isEmpty()))
1069          pDom->name.setValue(pDom->getBaseDomainReference()->getId());
1070      }
1071    }
1072
1073    setAxisList();
1074    it = axisList_.begin(); itE = axisList_.end();
1075    for (; it != itE; ++it)
1076    {
1077      CAxis* pAxis = CAxis::get(*it);
1078      if (context->hasClient)
1079      {
1080        pAxis->solveRefInheritance(apply);
1081        pAxis->solveBaseReference();
1082        if ((!pAxis->axis_ref.isEmpty()) && (pAxis->name.isEmpty()))
1083          pAxis->name.setValue(pAxis->getBaseAxisReference()->getId());
1084      }
1085    }
1086  }
1087
1088  /*!
1089  \brief Get the list of domain pointers
1090  \return list of domain pointers
1091  */
1092  std::vector<CDomain*> CGrid::getDomains()
1093  {
1094    std::vector<CDomain*> domList;
1095    if (!domList_.empty())
1096    {
1097      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1098    }
1099    return domList;
1100  }
1101
1102  /*!
1103  \brief Get the list of  axis pointers
1104  \return list of axis pointers
1105  */
1106  std::vector<CAxis*> CGrid::getAxis()
1107  {
1108    std::vector<CAxis*> aList;
1109    if (!axisList_.empty())
1110      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1111
1112    return aList;
1113  }
1114
1115  /*!
1116  \brief Set domain(s) of a grid from a list
1117  \param[in] domains list of domains
1118  */
1119  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1120  {
1121    if (isDomListSet) return;
1122    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1123    if (!domains.empty() && domList.empty()) domList = domains;
1124    if (!domList.empty())
1125    {
1126      int sizeDom = domList.size();
1127      domList_.resize(sizeDom);
1128      for (int i = 0 ; i < sizeDom; ++i)
1129      {
1130        domList_[i] = domList[i]->getId();
1131      }
1132      isDomListSet = true;
1133    }
1134
1135  }
1136
1137  /*!
1138  \brief Set axis(s) of a grid from a list
1139  \param[in] axis list of axis
1140  */
1141  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1142  {
1143    if (isAxisListSet) return;
1144    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1145    if (!axis.empty() && aList.empty()) aList = axis;
1146    if (!aList.empty())
1147    {
1148      int sizeAxis = aList.size();
1149      axisList_.resize(sizeAxis);
1150      for (int i = 0; i < sizeAxis; ++i)
1151      {
1152        axisList_[i] = aList[i]->getId();
1153      }
1154      isAxisListSet = true;
1155    }
1156  }
1157
1158  /*!
1159  \brief Get list of id of domains
1160  \return id list of domains
1161  */
1162  std::vector<StdString> CGrid::getDomainList()
1163  {
1164    setDomainList();
1165    return domList_;
1166  }
1167
1168  /*!
1169  \brief Get list of id of axis
1170  \return id list of axis
1171  */
1172  std::vector<StdString> CGrid::getAxisList()
1173  {
1174    setAxisList();
1175    return axisList_;
1176  }
1177
1178  void CGrid::sendAllDomains()
1179  {
1180    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1181    int dSize = domList.size();
1182    for (int i = 0; i < dSize; ++i)
1183    {
1184      sendAddDomain(domList[i]->getId());
1185      domList[i]->sendAllAttributesToServer();
1186    }
1187  }
1188
1189  void CGrid::sendAllAxis()
1190  {
1191    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1192    int aSize = aList.size();
1193
1194    for (int i = 0; i < aSize; ++i)
1195    {
1196      sendAddAxis(aList[i]->getId());
1197      aList[i]->sendAllAttributesToServer();
1198    }
1199  }
1200
1201  void CGrid::parse(xml::CXMLNode & node)
1202  {
1203    SuperClass::parse(node);
1204
1205    // List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false)
1206    std::vector<bool> order;
1207
1208    if (node.goToChildElement())
1209    {
1210      StdString domainName("domain");
1211      StdString axisName("axis");
1212      do
1213      {
1214        if (node.getElementName() == domainName) {
1215          order.push_back(true);
1216          this->getVirtualDomainGroup()->parseChild(node);
1217        }
1218        if (node.getElementName() == axisName) {
1219          order.push_back(false);
1220          this->getVirtualAxisGroup()->parseChild(node);
1221        }
1222      } while (node.goToNextElement()) ;
1223      node.goToParentElement();
1224    }
1225
1226    if (!order.empty())
1227    {
1228      int sizeOrd = order.size();
1229      axis_domain_order.resize(sizeOrd);
1230      for (int i = 0; i < sizeOrd; ++i)
1231      {
1232        axis_domain_order(i) = order[i];
1233      }
1234      scalar_grid = false;
1235    }
1236    else scalar_grid = true;
1237
1238    setDomainList();
1239    setAxisList();
1240   }
1241
1242} // namespace xios
Note: See TracBrowser for help on using the repository browser.