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

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

Grid: Remove scalar_grid attribute.

It always was for internal use only. This avoids having to remove part of the automatically generated Fortran interface.

  • 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.9 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 (!isScalarGrid())
170     {
171       std::vector<int> dataNindex = clientDistribution_->getDataNIndex();
172       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];
173     }
174     return retvalue;
175   }
176
177   std::map<int, StdSize> CGrid::getConnectedServerDataSize()
178   {
179     double secureFactor = 2.5 * sizeof(double) * CXios::bufferServerFactorSize;
180     StdSize retVal = 1;
181     std::map<int, StdSize> ret;
182     std::map<int, size_t >::const_iterator itb = connectedDataSize_.begin(), it, itE = connectedDataSize_.end();
183
184     if (isScalarGrid())
185     {
186       for (it = itb; it != itE; ++it)
187       {
188         retVal *= secureFactor;
189         ret.insert(std::make_pair(it->first, retVal));
190       }
191       return ret;
192     }
193
194     for (it = itb; it != itE; ++it)
195     {
196        retVal = it->second;
197        retVal *= secureFactor;
198        ret.insert(std::make_pair<int,StdSize>(it->first, retVal));
199     }
200
201     if (connectedDataSize_.empty())
202     {
203       for (int i = 0; i < connectedServerRank_.size(); ++i)
204       {
205         retVal = 1;
206         retVal *= secureFactor;
207         ret.insert(std::make_pair<int,StdSize>(connectedServerRank_[i], retVal));
208       }
209     }
210
211     return ret;
212   }
213
214
215   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
216   {
217     if (this->isDomainAxisChecked) return;
218
219     this->solveAxisRef(areAttributesChecked);
220     this->solveDomainRef(areAttributesChecked);
221
222     this->isDomainAxisChecked = areAttributesChecked;
223   }
224
225   void CGrid::checkMaskIndex(bool doSendingIndex)
226   {
227     CContext* context = CContext::getCurrent() ;
228     CContextClient* client=context->client ;
229
230     if (isScalarGrid())
231     {
232       if (context->hasClient)
233          if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndexScalarGrid(); this->isIndexSent = true; }
234
235       if (this->isChecked) return;
236       if (context->hasClient)
237       {
238          this->computeIndexScalarGrid();
239       }
240
241       this->isChecked = true;
242       return;
243     }
244
245     if (context->hasClient)
246      if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndex(); this->isIndexSent = true; }
247
248     if (this->isChecked) return;
249
250     if (context->hasClient)
251     {
252        checkMask() ;
253        this->computeIndex() ;
254        this->storeIndex.push_front(new CArray<int,1>() );
255     }
256     this->isChecked = true;
257   }
258
259   void CGrid::checkMask(void)
260   {
261      using namespace std;
262      std::vector<CDomain*> domainP = this->getDomains();
263      std::vector<CAxis*> axisP = this->getAxis();
264      int dim = domainP.size() * 2 + axisP.size();
265
266      std::vector<CArray<bool,2>* > domainMasks(domainP.size());
267      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask);
268      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
269      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
270
271      switch (dim) {
272        case 1:
273          checkGridMask(mask1, domainMasks, axisMasks, axis_domain_order);
274          break;
275        case 2:
276          checkGridMask(mask2, domainMasks, axisMasks, axis_domain_order);
277          break;
278        case 3:
279          checkGridMask(mask3, domainMasks, axisMasks, axis_domain_order);
280          break;
281//        case 4:
282//          checkGridMask(mask4, domainMasks, axisMasks, axis_domain_order);
283//          break;
284//        case 5:
285//          checkGridMask(mask5, domainMasks, axisMasks, axis_domain_order);
286//          break;
287//        case 6:
288//          checkGridMask(mask6, domainMasks, axisMasks, axis_domain_order);
289//          break;
290//        case 7:
291//          checkGridMask(mask7, domainMasks, axisMasks, axis_domain_order);
292//          break;
293        default:
294          break;
295      }
296   }
297   //---------------------------------------------------------------
298
299   void CGrid::solveDomainRef(bool sendAtt)
300   {
301      setDomainList();
302      std::vector<CDomain*> domListP = this->getDomains();
303      if (!domListP.empty())
304      {
305        computeGridGlobalDimension(getDomains(), getAxis(), axis_domain_order);
306        for (int i = 0; i < domListP.size(); ++i)
307        {
308          if (sendAtt) domListP[i]->sendCheckedAttributes();
309          else domListP[i]->checkAttributesOnClient();
310        }
311      }
312   }
313
314   //---------------------------------------------------------------
315
316   void CGrid::solveAxisRef(bool sendAtt)
317   {
318      setAxisList();
319      std::vector<CAxis*> axisListP = this->getAxis();
320      if (!axisListP.empty())
321      {
322        int idx = 0;
323        std::vector<int> axisPositionMap;
324        for (int i = 0; i < axis_domain_order.numElements(); ++i)
325        {
326          if (false == axis_domain_order(i))
327          {
328            axisPositionMap.push_back(idx);
329            ++idx;
330          }
331          else idx += 2;
332        }
333
334        computeGridGlobalDimension(getDomains(), getAxis(), axis_domain_order);
335        for (int i = 0; i < axisListP.size(); ++i)
336        {
337          if (sendAtt)
338            axisListP[i]->sendCheckedAttributes(globalDim_,axisPositionMap[i]);
339          else
340            axisListP[i]->checkAttributesOnClient(globalDim_,axisPositionMap[i]);
341          ++idx;
342        }
343
344      }
345   }
346
347   //---------------------------------------------------------------
348
349   void CGrid::computeIndex(void)
350   {
351     CContext* context = CContext::getCurrent() ;
352     CContextClient* client=context->client ;
353
354     // First of all, compute distribution on client side
355     clientDistribution_ = new CDistributionClient(client->clientRank, this);
356     // Get local data index on client
357     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().numElements());
358     storeIndex_client = (clientDistribution_->getLocalDataIndexOnClient());
359     isDataDistributed_= clientDistribution_->isDataDistributed();
360
361     if (!doGridHaveDataDistributed())
362     {
363        if (0 == client->clientRank)
364        {
365          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().numElements();
366          for (int rank = 0; rank < client->serverSize; ++rank)
367            connectedDataSize_[rank] = ssize;
368        }
369        return;
370     }
371
372     // Compute mapping between client and server
373     size_t globalSizeIndex = 1, indexBegin, indexEnd;
374     int range, clientSize = client->clientSize;
375     for (int i = 0; i < globalDim_.size(); ++i) globalSizeIndex *= globalDim_[i];
376     indexBegin = 0;
377     for (int i = 0; i < clientSize; ++i)
378     {
379       range = globalSizeIndex / clientSize;
380       if (i < (globalSizeIndex%clientSize)) ++range;
381       if (i == client->clientRank) break;
382       indexBegin += range;
383     }
384     indexEnd = indexBegin + range - 1;
385
386     // Then compute distribution on server side
387     serverDistributionDescription_ = new CServerDistributionDescription(clientDistribution_->getNGlob());
388     serverDistributionDescription_->computeServerDistribution(client->serverSize, true);
389     serverDistributionDescription_->computeServerGlobalIndexInRange(client->serverSize,
390                                                                     std::make_pair<size_t,size_t>(indexBegin, indexEnd));
391
392     // Finally, compute index mapping between client(s) and server(s)
393     clientServerMap_ = new CClientServerMappingDistributed(serverDistributionDescription_->getGlobalIndexRange(),
394                                                            client->intraComm,
395                                                            clientDistribution_->isDataDistributed());
396
397     clientServerMap_->computeServerIndexMapping(clientDistribution_->getGlobalIndex());
398     const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
399     const CArray<size_t,1>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
400
401     std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
402     itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
403     iteGlobalMap = globalIndexOnServer.end();
404
405     int nbGlobalIndex = globalIndexSendToServer.numElements();
406    for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
407    {
408      int serverRank = itGlobalMap->first;
409      std::vector<size_t>::const_iterator itbVecGlobal = (itGlobalMap->second).begin(), itVecGlobal,
410                                          iteVecGlobal = (itGlobalMap->second).end();
411      for (int i = 0; i < nbGlobalIndex; ++i)
412      {
413        if (iteVecGlobal != std::find(itbVecGlobal, iteVecGlobal, globalIndexSendToServer(i)))
414        {
415          if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
416            connectedDataSize_[serverRank] = 1;
417          else
418            ++connectedDataSize_[serverRank];
419        }
420      }
421    }
422
423   connectedServerRank_.clear();
424   for (std::map<int, std::vector<size_t> >::const_iterator it = globalIndexOnServer.begin(); it != globalIndexOnServer.end(); ++it) {
425     connectedServerRank_.push_back(it->first);
426   }
427   if (!connectedDataSize_.empty())
428   {
429     connectedServerRank_.clear();
430     for (std::map<int,size_t>::const_iterator it = connectedDataSize_.begin(); it != connectedDataSize_.end(); ++it)
431       connectedServerRank_.push_back(it->first);
432   }
433
434    nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
435   }
436
437   //----------------------------------------------------------------
438
439   CGrid* CGrid::createGrid(CDomain* domain)
440   {
441      std::vector<CDomain*> vecDom(1,domain);
442      std::vector<CAxis*> vecAxis;
443
444      CGrid* grid = createGrid(vecDom, vecAxis);
445
446      return (grid);
447   }
448
449   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
450   {
451      std::vector<CDomain*> vecDom(1,domain);
452      std::vector<CAxis*> vecAxis(1,axis);
453      CGrid* grid = createGrid(vecDom, vecAxis);
454
455      return (grid);
456   }
457
458   CGrid* CGrid::createGrid(std::vector<CDomain*> domains, std::vector<CAxis*> axis)
459   {
460      StdString new_id = StdString("__");
461      if (!domains.empty()) for (int i = 0; i < domains.size(); ++i) new_id += domains[i]->getId() + StdString("_");
462      if (!axis.empty()) for (int i = 0; i < axis.size(); ++i) new_id += axis[i]->getId() + StdString("_") ;
463      if (domains.empty() && axis.empty()) new_id += StdString("scalar_grid");
464      new_id += StdString("_");
465
466      CGrid* grid = CGridGroup::get("grid_definition")->createChild(new_id) ;
467      grid->setDomainList(domains);
468      grid->setAxisList(axis);
469
470      //By default, domains are always the first ones of a grid
471      if (grid->axis_domain_order.isEmpty())
472      {
473        int size = domains.size()+axis.size();
474        grid->axis_domain_order.resize(size);
475        for (int i = 0; i < size; ++i)
476        {
477          if (i < domains.size()) grid->axis_domain_order(i) = true;
478          else grid->axis_domain_order(i) = false;
479        }
480      }
481
482      grid->computeGridGlobalDimension(domains, axis, grid->axis_domain_order);
483
484      return (grid);
485   }
486
487   CDomainGroup* CGrid::getVirtualDomainGroup() const
488   {
489     return (this->vDomainGroup_);
490   }
491
492   CAxisGroup* CGrid::getVirtualAxisGroup() const
493   {
494     return (this->vAxisGroup_);
495   }
496
497   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
498   {
499     CArray<size_t,1>& out_i=*outIndexFromClient[rank];
500     StdSize numElements = stored.numElements();
501     for (StdSize n = 0; n < numElements; ++n)
502     {
503       *(field+out_i(n)) = stored(n);
504     }
505   }
506
507   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
508   {
509     CArray<size_t,1>& out_i = *outIndexFromClient[rank];
510     StdSize numElements = stored.numElements();
511     for (StdSize n = 0; n < numElements; ++n)
512     {
513       stored(n) = *(field+out_i(n));
514     }
515   }
516
517   //----------------------------------------------------------------
518
519
520   void CGrid::storeField_arr
521      (const double * const data, CArray<double, 1>& stored) const
522   {
523      const StdSize size = storeIndex_client.numElements() ;
524
525      stored.resize(size) ;
526      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)] ;
527   }
528
529   void CGrid::restoreField_arr
530      (const CArray<double, 1>& stored, double * const data) const
531   {
532      const StdSize size = storeIndex_client.numElements() ;
533
534      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i) ;
535   }
536
537  void CGrid::computeIndexScalarGrid()
538  {
539    CContext* context = CContext::getCurrent();
540    CContextClient* client=context->client;
541
542    storeIndex_client.resize(1);
543    storeIndex_client[0] = 0;
544    if (0 == client->clientRank)
545    {
546      for (int rank = 0; rank < client->serverSize; ++rank)
547        connectedDataSize_[rank] = 1;
548    }
549    isDataDistributed_ = false;
550  }
551
552  void CGrid::sendIndexScalarGrid()
553  {
554    CContext* context = CContext::getCurrent() ;
555    CContextClient* client=context->client ;
556
557    CEventClient event(getType(),EVENT_ID_INDEX);
558    list<shared_ptr<CMessage> > list_msg ;
559    list< CArray<size_t,1>* > listOutIndex;
560    if (0 == client->clientRank)
561    {
562      for (int rank = 0; rank < client->serverSize; ++rank)
563      {
564        int nb = 1;
565        CArray<size_t, 1> outGlobalIndexOnServer(nb);
566        CArray<int, 1> outLocalIndexToServer(nb);
567        for (int k = 0; k < nb; ++k)
568        {
569          outGlobalIndexOnServer(k) = 0;
570          outLocalIndexToServer(k)  = 0;
571        }
572
573        storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer) ));
574        listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
575
576        list_msg.push_back(shared_ptr<CMessage>(new CMessage));
577        *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
578
579        event.push(rank, 1, *list_msg.back());
580      }
581      client->sendEvent(event);
582    }
583    else
584      client->sendEvent(event);
585
586    for(list<CArray<size_t,1>* >::iterator it=listOutIndex.begin();it!=listOutIndex.end();++it) delete *it ;
587  }
588
589  void CGrid::sendIndex(void)
590  {
591    CContext* context = CContext::getCurrent() ;
592    CContextClient* client=context->client ;
593
594    CEventClient event(getType(),EVENT_ID_INDEX) ;
595    int rank ;
596    list<shared_ptr<CMessage> > list_msg ;
597    list< CArray<size_t,1>* > listOutIndex;
598    const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
599    const CArray<int,1>& localIndexSendToServer = clientDistribution_->getLocalDataIndexSendToServer();
600    const CArray<size_t,1>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
601
602    if (!doGridHaveDataDistributed())
603    {
604      if (0 == client->clientRank)
605      {
606        CArray<size_t, 1> outGlobalIndexOnServer = globalIndexSendToServer;
607        CArray<int,1> outLocalIndexToServer = localIndexSendToServer;
608        for (rank = 0; rank < client->serverSize; ++rank)
609        {
610          storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer)));
611          listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
612
613          list_msg.push_back(shared_ptr<CMessage>(new CMessage));
614          *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
615
616          event.push(rank, 1, *list_msg.back());
617        }
618        client->sendEvent(event);
619      }
620      else
621        client->sendEvent(event);
622    }
623    else
624    {
625      std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
626      itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
627      iteGlobalMap = globalIndexOnServer.end();
628
629      int nbGlobalIndex = globalIndexSendToServer.numElements();
630      std::map<int,std::vector<int> >localIndexTmp;
631      std::map<int,std::vector<size_t> > globalIndexTmp;
632      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
633      {
634        int serverRank = itGlobalMap->first;
635        std::vector<size_t>::const_iterator itbVecGlobal = (itGlobalMap->second).begin(),
636                                            iteVecGlobal = (itGlobalMap->second).end();
637        for (int i = 0; i < nbGlobalIndex; ++i)
638        {
639          if (iteVecGlobal != std::find(itbVecGlobal, iteVecGlobal, globalIndexSendToServer(i)))
640          {
641            globalIndexTmp[serverRank].push_back(globalIndexSendToServer(i));
642            localIndexTmp[serverRank].push_back(localIndexSendToServer(i));
643          }
644        }
645      }
646
647      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
648      {
649        rank = connectedServerRank_[ns];
650        int nb = 0;
651        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
652          nb = globalIndexTmp[rank].size();
653
654        CArray<size_t, 1> outGlobalIndexOnServer(nb);
655        CArray<int, 1> outLocalIndexToServer(nb);
656        for (int k = 0; k < nb; ++k)
657        {
658          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
659          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
660        }
661
662        storeIndex_toSrv.insert( pair<int,CArray<int,1>* >(rank,new CArray<int,1>(outLocalIndexToServer) ));
663        listOutIndex.push_back(new CArray<size_t,1>(outGlobalIndexOnServer));
664
665        list_msg.push_back(shared_ptr<CMessage>(new CMessage));
666        *list_msg.back()<<getId()<<isDataDistributed_<<*listOutIndex.back();
667
668        event.push(rank, nbSenders[rank], *list_msg.back());
669      }
670
671      client->sendEvent(event);
672    }
673
674    for(list<CArray<size_t,1>* >::iterator it=listOutIndex.begin();it!=listOutIndex.end();++it) delete *it ;
675  }
676
677  void CGrid::recvIndex(CEventServer& event)
678  {
679    string gridId;
680    vector<int> ranks;
681    vector<CBufferIn*> buffers;
682
683    list<CEventServer::SSubEvent>::iterator it;
684    for (it=event.subEvents.begin();it!=event.subEvents.end();++it)
685    {
686      ranks.push_back(it->rank);
687      CBufferIn* buffer = it->buffer;
688      *buffer >> gridId;
689      buffers.push_back(buffer);
690    }
691    get(gridId)->recvIndex(ranks, buffers) ;
692  }
693
694  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
695                                         const std::vector<CAxis*>& axis,
696                                         const CArray<bool,1>& axisDomainOrder)
697  {
698    globalDim_.resize(domains.size()*2+axis.size());
699    int idx = 0, idxDomain = 0, idxAxis = 0;
700    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
701    {
702      if (axisDomainOrder(i))
703      {
704        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
705        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
706        ++idxDomain;
707        idx += 2;
708      }
709      else
710      {
711        globalDim_[idx] = axis[idxAxis]->size.getValue();
712        ++idxAxis;
713        ++idx;
714      }
715    }
716  }
717
718  std::vector<int> CGrid::getGlobalDimension()
719  {
720    return globalDim_;
721  }
722
723  bool CGrid::isScalarGrid() const
724  {
725    return (axisList_.empty() && domList_.empty());
726  }
727
728  /*!
729    Verify whether one server need to write data
730    There are some cases on which one server has nodata to write. For example, when we
731  just only want to zoom on a domain.
732  */
733  bool CGrid::doGridHaveDataToWrite()
734  {
735    size_t ssize = 0;
736    for (map<int, CArray<size_t, 1>* >::const_iterator it = outIndexFromClient.begin();
737                                                       it != outIndexFromClient.end(); ++it)
738    {
739      ssize += (it->second)->numElements();
740    }
741    return (0 != ssize);
742  }
743
744  /*!
745    Return size of data which is written on each server
746    Whatever dimension of a grid, data which are written on server must be presented as
747  an one dimension array.
748  \return size of data written on server
749  */
750  size_t CGrid::getWrittenDataSize() const
751  {
752    return writtenDataSize_;
753  }
754
755  const CDistributionServer* CGrid::getDistributionServer() const
756  {
757    return serverDistribution_;
758  }
759
760  bool CGrid::doGridHaveDataDistributed()
761  {
762    if (isScalarGrid()) return false;
763    else
764      return isDataDistributed_;
765  }
766
767  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
768  {
769    CContext* context = CContext::getCurrent();
770    CContextServer* server = context->server;
771
772    for (int n = 0; n < ranks.size(); n++)
773    {
774      int rank = ranks[n];
775      CBufferIn& buffer = *buffers[n];
776
777      buffer >> isDataDistributed_;
778      size_t dataSize = 0;
779
780      if (isScalarGrid())
781      {
782        writtenDataSize_ = 1;
783        CArray<size_t,1> outIndex;
784        buffer >> outIndex;
785        outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
786        std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
787        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
788                                                      nZoomBeginGlobal, nGlob);
789        return;
790      }
791
792      if (0 == serverDistribution_)
793      {
794        int idx = 0, numElement = axis_domain_order.numElements();
795        int ssize = numElement;
796        std::vector<int> indexMap(numElement);
797        for (int i = 0; i < numElement; ++i)
798        {
799          indexMap[i] = idx;
800          if (true == axis_domain_order(i))
801          {
802            ++ssize;
803            idx += 2;
804          }
805          else
806            ++idx;
807        }
808
809        int axisId = 0, domainId = 0;
810        std::vector<CDomain*> domainList = getDomains();
811        std::vector<CAxis*> axisList = getAxis();
812        std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
813        for (int i = 0; i < numElement; ++i)
814        {
815          if (axis_domain_order(i))
816          {
817            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
818            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
819            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->zoom_ibegin;
820            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
821
822            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
823            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
824            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin;
825            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
826            ++domainId;
827          }
828          else
829          {
830            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
831            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
832            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->zoom_begin;
833            nGlob[indexMap[i]] = axisList[axisId]->size;
834            ++axisId;
835          }
836        }
837        dataSize = 1;
838        for (int i = 0; i < nZoomSize.size(); ++i)
839          dataSize *= nZoomSize[i];
840
841        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
842                                                      nZoomBeginGlobal, nGlob);
843      }
844
845      CArray<size_t,1> outIndex;
846      buffer >> outIndex;
847      if (isDataDistributed_)
848        serverDistribution_->computeLocalIndex(outIndex);
849      else
850      {
851        dataSize = outIndex.numElements();
852        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
853      }
854      writtenDataSize_ += dataSize;
855
856      outIndexFromClient.insert(std::pair<int, CArray<size_t,1>* >(rank, new CArray<size_t,1>(outIndex)));
857      connectedDataSize_[rank] = outIndex.numElements();
858    }
859
860    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
861  }
862
863   /*!
864   \brief Dispatch event received from client
865      Whenever a message is received in buffer of server, it will be processed depending on
866   its event type. A new event type should be added in the switch list to make sure
867   it processed on server side.
868   \param [in] event: Received message
869   */
870  bool CGrid::dispatchEvent(CEventServer& event)
871  {
872
873    if (SuperClass::dispatchEvent(event)) return true ;
874    else
875    {
876      switch(event.type)
877      {
878        case EVENT_ID_INDEX :
879          recvIndex(event) ;
880          return true ;
881          break ;
882
883         case EVENT_ID_ADD_DOMAIN :
884           recvAddDomain(event) ;
885           return true ;
886           break ;
887
888         case EVENT_ID_ADD_AXIS :
889           recvAddAxis(event) ;
890           return true ;
891           break ;
892        default :
893          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
894                <<"Unknown Event") ;
895          return false ;
896      }
897    }
898  }
899
900   void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const
901   {
902      if ((this->storeIndex.size()-1 ) != storedClient.size())
903         ERROR("void CGrid::inputFieldServer(const std::deque< CArray<double, 1>* > storedClient, CArray<double, 1>&  storedServer) const",
904                << "[ Expected received field = " << (this->storeIndex.size()-1) << ", "
905                << "[ received fiedl = "    << storedClient.size() << "] "
906                << "Data from clients are missing!") ;
907      storedServer.resize(storeIndex[0]->numElements());
908
909      for (StdSize i = 0, n = 0; i < storedClient.size(); i++)
910         for (StdSize j = 0; j < storedClient[i]->numElements(); j++)
911            storedServer(n++) = (*storedClient[i])(j);
912   }
913
914   void CGrid::outputFieldToServer(CArray<double,1>& fieldIn, int rank, CArray<double,1>& fieldOut)
915   {
916     CArray<int,1>& index = *storeIndex_toSrv[rank] ;
917     int nb=index.numElements() ;
918     fieldOut.resize(nb) ;
919
920     for(int k=0;k<nb;k++) fieldOut(k)=fieldIn(index(k)) ;
921    }
922   ///---------------------------------------------------------------
923
924   CDomain* CGrid::addDomain(const std::string& id)
925   {
926     return vDomainGroup_->createChild(id) ;
927   }
928
929   CAxis* CGrid::addAxis(const std::string& id)
930   {
931     return vAxisGroup_->createChild(id) ;
932   }
933
934   //! Change virtual field group to a new one
935   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
936   {
937      this->vDomainGroup_ = newVDomainGroup;
938   }
939
940   //! Change virtual variable group to new one
941   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
942   {
943      this->vAxisGroup_ = newVAxisGroup;
944   }
945
946   //----------------------------------------------------------------
947   //! Create virtual field group, which is done normally on initializing file
948   void CGrid::setVirtualDomainGroup(void)
949   {
950      this->setVirtualDomainGroup(CDomainGroup::create());
951   }
952
953   //! Create virtual variable group, which is done normally on initializing file
954   void CGrid::setVirtualAxisGroup(void)
955   {
956      this->setVirtualAxisGroup(CAxisGroup::create());
957   }
958
959   /*!
960   \brief Send a message to create a domain on server side
961   \param[in] id String identity of domain that will be created on server
962   */
963   void CGrid::sendAddDomain(const string& id)
964   {
965    CContext* context=CContext::getCurrent() ;
966
967    if (! context->hasServer )
968    {
969       CContextClient* client=context->client ;
970
971       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN) ;
972       if (client->isServerLeader())
973       {
974         CMessage msg ;
975         msg<<this->getId() ;
976         msg<<id ;
977         const std::list<int>& ranks = client->getRanksServerLeader();
978         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
979           event.push(*itRank,1,msg);
980         client->sendEvent(event) ;
981       }
982       else client->sendEvent(event) ;
983    }
984   }
985
986   /*!
987   \brief Send a message to create an axis on server side
988   \param[in] id String identity of axis that will be created on server
989   */
990   void CGrid::sendAddAxis(const string& id)
991   {
992    CContext* context=CContext::getCurrent() ;
993
994    if (! context->hasServer )
995    {
996       CContextClient* client=context->client ;
997
998       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS) ;
999       if (client->isServerLeader())
1000       {
1001         CMessage msg ;
1002         msg<<this->getId() ;
1003         msg<<id ;
1004         const std::list<int>& ranks = client->getRanksServerLeader();
1005         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1006           event.push(*itRank,1,msg);
1007         client->sendEvent(event) ;
1008       }
1009       else client->sendEvent(event) ;
1010    }
1011   }
1012
1013   /*!
1014   \brief Receive a message annoucing the creation of a domain on server side
1015   \param[in] event Received event
1016   */
1017   void CGrid::recvAddDomain(CEventServer& event)
1018   {
1019
1020      CBufferIn* buffer=event.subEvents.begin()->buffer;
1021      string id;
1022      *buffer>>id ;
1023      get(id)->recvAddDomain(*buffer) ;
1024   }
1025
1026   /*!
1027   \brief Receive a message annoucing the creation of a domain on server side
1028   \param[in] buffer Buffer containing message
1029   */
1030   void CGrid::recvAddDomain(CBufferIn& buffer)
1031   {
1032      string id ;
1033      buffer>>id ;
1034      addDomain(id) ;
1035   }
1036
1037   /*!
1038   \brief Receive a message annoucing the creation of an axis on server side
1039   \param[in] event Received event
1040   */
1041   void CGrid::recvAddAxis(CEventServer& event)
1042   {
1043
1044      CBufferIn* buffer=event.subEvents.begin()->buffer;
1045      string id;
1046      *buffer>>id ;
1047      get(id)->recvAddAxis(*buffer) ;
1048   }
1049
1050   /*!
1051   \brief Receive a message annoucing the creation of an axis on server side
1052   \param[in] buffer Buffer containing message
1053   */
1054   void CGrid::recvAddAxis(CBufferIn& buffer)
1055   {
1056      string id ;
1057      buffer>>id ;
1058      addAxis(id) ;
1059   }
1060
1061  /*!
1062  \brief Solve domain and axis references
1063  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1064  all attributes from their parents, they should be processed with this function
1065  \param[in] apply inherit all attributes of parents (true)
1066  */
1067  void CGrid::solveDomainAxisRefInheritance(bool apply)
1068  {
1069    CContext* context = CContext::getCurrent();
1070    unsigned int vecSize, i;
1071    std::vector<StdString>::iterator it, itE;
1072    setDomainList();
1073    it = domList_.begin(); itE = domList_.end();
1074    for (; it != itE; ++it)
1075    {
1076      CDomain* pDom = CDomain::get(*it);
1077      if (context->hasClient)
1078      {
1079        pDom->solveRefInheritance(apply);
1080        pDom->solveBaseReference();
1081        if ((!pDom->domain_ref.isEmpty()) && (pDom->name.isEmpty()))
1082          pDom->name.setValue(pDom->getBaseDomainReference()->getId());
1083      }
1084    }
1085
1086    setAxisList();
1087    it = axisList_.begin(); itE = axisList_.end();
1088    for (; it != itE; ++it)
1089    {
1090      CAxis* pAxis = CAxis::get(*it);
1091      if (context->hasClient)
1092      {
1093        pAxis->solveRefInheritance(apply);
1094        pAxis->solveBaseReference();
1095        if ((!pAxis->axis_ref.isEmpty()) && (pAxis->name.isEmpty()))
1096          pAxis->name.setValue(pAxis->getBaseAxisReference()->getId());
1097      }
1098    }
1099  }
1100
1101  /*!
1102  \brief Get the list of domain pointers
1103  \return list of domain pointers
1104  */
1105  std::vector<CDomain*> CGrid::getDomains()
1106  {
1107    std::vector<CDomain*> domList;
1108    if (!domList_.empty())
1109    {
1110      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1111    }
1112    return domList;
1113  }
1114
1115  /*!
1116  \brief Get the list of  axis pointers
1117  \return list of axis pointers
1118  */
1119  std::vector<CAxis*> CGrid::getAxis()
1120  {
1121    std::vector<CAxis*> aList;
1122    if (!axisList_.empty())
1123      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1124
1125    return aList;
1126  }
1127
1128  /*!
1129  \brief Set domain(s) of a grid from a list
1130  \param[in] domains list of domains
1131  */
1132  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1133  {
1134    if (isDomListSet) return;
1135    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1136    if (!domains.empty() && domList.empty()) domList = domains;
1137    if (!domList.empty())
1138    {
1139      int sizeDom = domList.size();
1140      domList_.resize(sizeDom);
1141      for (int i = 0 ; i < sizeDom; ++i)
1142      {
1143        domList_[i] = domList[i]->getId();
1144      }
1145      isDomListSet = true;
1146    }
1147
1148  }
1149
1150  /*!
1151  \brief Set axis(s) of a grid from a list
1152  \param[in] axis list of axis
1153  */
1154  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1155  {
1156    if (isAxisListSet) return;
1157    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1158    if (!axis.empty() && aList.empty()) aList = axis;
1159    if (!aList.empty())
1160    {
1161      int sizeAxis = aList.size();
1162      axisList_.resize(sizeAxis);
1163      for (int i = 0; i < sizeAxis; ++i)
1164      {
1165        axisList_[i] = aList[i]->getId();
1166      }
1167      isAxisListSet = true;
1168    }
1169  }
1170
1171  /*!
1172  \brief Get list of id of domains
1173  \return id list of domains
1174  */
1175  std::vector<StdString> CGrid::getDomainList()
1176  {
1177    setDomainList();
1178    return domList_;
1179  }
1180
1181  /*!
1182  \brief Get list of id of axis
1183  \return id list of axis
1184  */
1185  std::vector<StdString> CGrid::getAxisList()
1186  {
1187    setAxisList();
1188    return axisList_;
1189  }
1190
1191  void CGrid::sendAllDomains()
1192  {
1193    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1194    int dSize = domList.size();
1195    for (int i = 0; i < dSize; ++i)
1196    {
1197      sendAddDomain(domList[i]->getId());
1198      domList[i]->sendAllAttributesToServer();
1199    }
1200  }
1201
1202  void CGrid::sendAllAxis()
1203  {
1204    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1205    int aSize = aList.size();
1206
1207    for (int i = 0; i < aSize; ++i)
1208    {
1209      sendAddAxis(aList[i]->getId());
1210      aList[i]->sendAllAttributesToServer();
1211    }
1212  }
1213
1214  void CGrid::parse(xml::CXMLNode & node)
1215  {
1216    SuperClass::parse(node);
1217
1218    // List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false)
1219    std::vector<bool> order;
1220
1221    if (node.goToChildElement())
1222    {
1223      StdString domainName("domain");
1224      StdString axisName("axis");
1225      do
1226      {
1227        if (node.getElementName() == domainName) {
1228          order.push_back(true);
1229          this->getVirtualDomainGroup()->parseChild(node);
1230        }
1231        if (node.getElementName() == axisName) {
1232          order.push_back(false);
1233          this->getVirtualAxisGroup()->parseChild(node);
1234        }
1235      } while (node.goToNextElement()) ;
1236      node.goToParentElement();
1237    }
1238
1239    if (!order.empty())
1240    {
1241      int sizeOrd = order.size();
1242      axis_domain_order.resize(sizeOrd);
1243      for (int i = 0; i < sizeOrd; ++i)
1244      {
1245        axis_domain_order(i) = order[i];
1246      }
1247    }
1248
1249    setDomainList();
1250    setAxisList();
1251   }
1252
1253} // namespace xios
Note: See TracBrowser for help on using the repository browser.