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

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

Implement reading fields from NetCDF files.

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