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

Last change on this file since 660 was 660, checked in by mhnguyen, 9 years ago

Adding interpolation test_remap

+) Add new test case for domain interpolation
+) Resolve circular dependence
+) Add function to read weigh file

Test
+) On Curie
+) test_remap can print out .nc

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