source: XIOS/trunk/src/node/field.cpp @ 623

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

Implementing transformation algorithm: zoom axis (local commit)

+) Implement zoom axis: zoomed points are points not masked
+) Correct some minor bugs

Test
+) Ok with normal cases: zoom in the last of transformation list
+) There is still a bug in case of zoom then inverse

  • 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: 42.9 KB
Line 
1#include "field.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6
7#include "node_type.hpp"
8#include "calendar_util.hpp"
9#include "message.hpp"
10#include "xios_spl.hpp"
11#include "type.hpp"
12#include "context_client.hpp"
13#include "context_server.hpp"
14#include <set>
15#include "axis_filter.hpp"
16#include "invert_algorithm.hpp"
17
18namespace xios{
19
20   /// ////////////////////// Définitions ////////////////////// ///
21
22   CField::CField(void)
23      : CObjectTemplate<CField>(), CFieldAttributes()
24      , refObject(), baseRefObject()
25      , grid(), file()
26      , freq_operation(), freq_write()
27      , nstep(0), nstepMax(0), isEOF(false)
28      , last_Write(), last_operation()
29      , foperation(), hasInstantData(false), hasExpression(false)
30      , active(false) , hasOutputFile(false),hasFieldOut(false), slotUpdateDate(NULL)
31      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false), filter(0)
32      , isReadDataRequestPending(false)
33      , filterSources_(), algorithms_()
34      { setVirtualVariableGroup(); }
35
36   CField::CField(const StdString& id)
37      : CObjectTemplate<CField>(id), CFieldAttributes()
38      , refObject(), baseRefObject()
39      , grid(), file()
40      , freq_operation(), freq_write()
41      , nstep(0), nstepMax(0), isEOF(false)
42      , last_Write(), last_operation()
43      , foperation(), hasInstantData(false), hasExpression(false)
44      , active(false), hasOutputFile(false), hasFieldOut(false), slotUpdateDate(NULL)
45      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false), filter(0)
46      , isReadDataRequestPending(false)
47      , filterSources_(), algorithms_()
48   { setVirtualVariableGroup(); }
49
50   CField::~CField(void)
51   {
52//      this->grid.reset();
53//      this->file.reset();
54      this->foperation.reset();
55      if (hasExpression) delete expression;
56      if (slotUpdateDate != NULL) delete slotUpdateDate;
57      if (0 != filter) delete filter;
58
59   }
60
61
62  //----------------------------------------------------------------
63
64   void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
65   {
66      this->vVariableGroup = newVVariableGroup;
67   }
68
69   void CField::setVirtualVariableGroup(void)
70   {
71      this->setVirtualVariableGroup(CVariableGroup::create());
72   }
73
74   CVariableGroup* CField::getVirtualVariableGroup(void) const
75   {
76      return this->vVariableGroup;
77   }
78
79
80   std::vector<CVariable*> CField::getAllVariables(void) const
81   {
82      return this->vVariableGroup->getAllChildren();
83   }
84
85   void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent)
86   {
87      SuperClassAttribute::setAttributes(parent, apply);
88      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
89   }
90   //----------------------------------------------------------------
91   //----------------------------------------------------------------
92
93   bool CField::updateDataServer
94      (const CDate& currDate,
95       const std::deque< CArray<double, 1>* > storedClient)
96   {
97      const CDate opeDate      = *last_operation + freq_operation;
98      const CDate writeDate    = *last_Write     + freq_write;
99
100      if (opeDate <= currDate)
101      {
102         if (this->data.numElements() != this->grid->storeIndex[0]->numElements())
103         {
104            this->data.resize(this->grid->storeIndex[0]->numElements());
105         }
106         CArray<double,1> input(data.numElements());
107         this->grid->inputFieldServer(storedClient, input);
108         (*this->foperation)(input);
109         *last_operation = currDate;
110      }
111      if (writeDate < (currDate + freq_operation))
112      {
113         this->foperation->final();
114         this->incrementNStep();
115         *last_Write = writeDate;
116         return true;
117      }
118      return false;
119   }
120
121  bool CField::dispatchEvent(CEventServer& event)
122  {
123    if (SuperClass::dispatchEvent(event)) return true;
124    else
125    {
126      switch(event.type)
127      {
128        case EVENT_ID_UPDATE_DATA :
129          recvUpdateData(event);
130          return true;
131          break;
132
133        case EVENT_ID_READ_DATA :
134          recvReadDataRequest(event);
135          return true;
136          break;
137
138        case EVENT_ID_READ_DATA_READY :
139          recvReadDataReady(event);
140          return true;
141          break;
142
143        case EVENT_ID_ADD_VARIABLE :
144          recvAddVariable(event);
145          return true;
146          break;
147
148        case EVENT_ID_ADD_VARIABLE_GROUP :
149          recvAddVariableGroup(event);
150          return true;
151          break;
152
153        default :
154          ERROR("bool CField::dispatchEvent(CEventServer& event)", << "Unknown Event");
155          return false;
156      }
157    }
158  }
159
160  void CField::sendUpdateData(void)
161  {
162    CContext* context = CContext::getCurrent();
163    CContextClient* client = context->client;
164
165    CEventClient event(getType(),EVENT_ID_UPDATE_DATA);
166
167    map<int,CArray<int, 1>* >::iterator it;
168    list<shared_ptr<CMessage> > list_msg;
169    list< CArray<double,1>* > list_data;
170
171    if (!grid->doGridHaveDataDistributed())
172    {
173       if (0 == client->clientRank)
174       {
175          for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
176          {
177            int rank=(*it).first ;
178            CArray<int,1>& index = *(it->second) ;
179                       std::cout << "rank " << index << std::endl;
180                       std::cout << "data " << data << std::endl;
181            CArray<double,1> data_tmp(index.numElements()) ;
182            for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
183
184            list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
185            list_data.push_back(new CArray<double,1>(data_tmp)) ;
186            *list_msg.back()<<getId()<<*list_data.back() ;
187            event.push(rank,1,*list_msg.back()) ;
188          }
189          client->sendEvent(event) ;
190       } else client->sendEvent(event);
191    }
192    else
193    {
194      for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
195      {
196        int rank=(*it).first ;
197        CArray<int,1>& index = *(it->second) ;
198        CArray<double,1> data_tmp(index.numElements()) ;
199        for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
200        list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
201        list_data.push_back(new CArray<double,1>(data_tmp)) ;
202        *list_msg.back()<<getId()<<*list_data.back() ;
203        event.push(rank,grid->nbSenders[rank],*list_msg.back()) ;
204      }
205      client->sendEvent(event) ;
206    }
207
208    for (list< CArray<double,1>* >::iterator it = list_data.begin(); it != list_data.end(); it++) delete *it;
209  }
210
211  void CField::recvUpdateData(CEventServer& event)
212  {
213    vector<int> ranks;
214    vector<CBufferIn*> buffers;
215
216    list<CEventServer::SSubEvent>::iterator it;
217    string fieldId;
218
219    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
220    {
221      int rank = it->rank;
222      CBufferIn* buffer = it->buffer;
223      *buffer >> fieldId;
224      ranks.push_back(rank);
225      buffers.push_back(buffer);
226    }
227    get(fieldId)->recvUpdateData(ranks,buffers);
228  }
229
230  void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
231  {
232    if (data_srv.empty())
233    {
234      for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
235      {
236        int rank = it->first;
237        CArray<double,1> data_tmp(it->second->numElements());
238        data_srv.insert( pair<int, CArray<double,1>* >(rank, new CArray<double,1>(data_tmp)));
239        foperation_srv.insert(pair<int,boost::shared_ptr<func::CFunctor> >(rank,boost::shared_ptr<func::CFunctor>(new func::CInstant(*data_srv[rank]))));
240      }
241    }
242
243    CContext* context = CContext::getCurrent();
244    const CDate& currDate = context->getCalendar()->getCurrentDate();
245    const CDate opeDate      = *last_operation_srv + freq_operation_srv;
246    const CDate writeDate    = *last_Write_srv     + freq_write_srv;
247
248    if (opeDate <= currDate)
249    {
250      for (int n = 0; n < ranks.size(); n++)
251      {
252        CArray<double,1> data_tmp;
253        *buffers[n] >> data_tmp;
254        (*foperation_srv[ranks[n]])(data_tmp);
255      }
256      *last_operation_srv = currDate;
257    }
258
259    if (writeDate < (currDate + freq_operation_srv))
260    {
261      for (int n = 0; n < ranks.size(); n++)
262      {
263        this->foperation_srv[ranks[n]]->final();
264      }
265
266      *last_Write_srv = writeDate;
267      writeField();
268      *lastlast_Write_srv = *last_Write_srv;
269    }
270  }
271
272  void CField::writeField(void)
273  {
274    if (!getRelFile()->allDomainEmpty)
275    {
276      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
277      {
278        getRelFile()->checkFile();
279        this->incrementNStep();
280        getRelFile()->getDataOutput()->writeFieldData(CField::get(this));
281      }
282    }
283  }
284
285  void CField::sendReadDataRequest(void)
286  {
287    CContext* context = CContext::getCurrent();
288    CContextClient* client = context->client;
289
290    CEventClient event(getType(), EVENT_ID_READ_DATA);
291    if (client->isServerLeader())
292    {
293      CMessage msg;
294      msg << getId();
295      const std::list<int>& ranks = client->getRanksServerLeader();
296      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
297        event.push(*itRank, 1, msg);
298      client->sendEvent(event);
299    }
300    else client->sendEvent(event);
301
302    lastDataRequestedFromServer = context->getCalendar()->getCurrentDate();
303    isReadDataRequestPending = true;
304  }
305
306  /*!
307  Send request new data read from file if need be, that is the current data is out-of-date.
308  \return true if and only if some data was requested
309  */
310  bool CField::sendReadDataRequestIfNeeded(void)
311  {
312    const CDate& currentDate = CContext::getCurrent()->getCalendar()->getCurrentDate();
313
314    bool requestData = (currentDate >= lastDataRequestedFromServer + file->output_freq.getValue());
315
316    if (requestData)
317      sendReadDataRequest();
318
319    return requestData;
320  }
321
322  void CField::recvReadDataRequest(CEventServer& event)
323  {
324    CBufferIn* buffer = event.subEvents.begin()->buffer;
325    StdString fieldId;
326    *buffer >> fieldId;
327    get(fieldId)->recvReadDataRequest();
328  }
329
330  void CField::recvReadDataRequest(void)
331  {
332    CContext* context = CContext::getCurrent();
333    CContextClient* client = context->client;
334
335    CEventClient event(getType(), EVENT_ID_READ_DATA_READY);
336    std::list<CMessage> msgs;
337
338    bool hasData = readField();
339
340    map<int, CArray<double,1>* >::iterator it;
341    for (it = data_srv.begin(); it != data_srv.end(); it++)
342    {
343      msgs.push_back(CMessage());
344      CMessage& msg = msgs.back();
345      msg << getId();
346      if (hasData)
347        msg << getNStep() - 1 << *it->second;
348      else
349        msg << size_t(-1);
350      event.push(it->first, grid->nbSenders[it->first], msg);
351    }
352    client->sendEvent(event);
353  }
354
355  bool CField::readField(void)
356  {
357    if (!getRelFile()->allDomainEmpty)
358    {
359      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
360      {
361        if (data_srv.empty())
362        {
363          for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
364            data_srv.insert(pair<int, CArray<double,1>*>(it->first, new CArray<double,1>(it->second->numElements())));
365        }
366
367        getRelFile()->checkFile();
368        this->incrementNStep();
369
370        if (!nstepMax)
371        {
372          nstepMax = getRelFile()->getDataInput()->getFieldNbRecords(CField::get(this));
373        }
374
375        if (getNStep() > nstepMax)
376          return false;
377
378        getRelFile()->getDataInput()->readFieldData(CField::get(this));
379      }
380    }
381
382    return true;
383  }
384
385  void CField::recvReadDataReady(CEventServer& event)
386  {
387    string fieldId;
388    vector<int> ranks;
389    vector<CBufferIn*> buffers;
390
391    list<CEventServer::SSubEvent>::iterator it;
392    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
393    {
394      ranks.push_back(it->rank);
395      CBufferIn* buffer = it->buffer;
396      *buffer >> fieldId;
397      buffers.push_back(buffer);
398    }
399    get(fieldId)->recvReadDataReady(ranks, buffers);
400  }
401
402  void CField::recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers)
403  {
404    CContext* context = CContext::getCurrent();
405    StdSize record;
406    for (int i = 0; i < ranks.size(); i++)
407    {
408      int rank = ranks[i];
409      *buffers[i] >> record;
410      isEOF = (record == size_t(-1));
411
412      if (!isEOF)
413      {
414        CArray<int,1>& index = *grid->storeIndex_toSrv[rank];
415        CArray<double,1> data_tmp(index.numElements());
416        *buffers[i] >> data_tmp;
417        for (int n = 0; n < data_tmp.numElements(); n++)
418          instantData(index(n)) = data_tmp(n);
419      }
420      else
421        break;
422    }
423
424    if (!isEOF)
425    {
426      for (list< pair<CField*, int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it)
427        it->first->setSlot(it->second);
428
429      if (!hasExpression) // Should be always true ?
430      {
431        const std::vector<CField*>& refField = getAllReference();
432        std::vector<CField*>::const_iterator it = refField.begin(), end = refField.end();
433
434        for (; it != end; it++) (*it)->setDataFromExpression(instantData);
435        if (hasFieldOut) updateDataFromExpression(instantData);
436      }
437    }
438
439    isReadDataRequestPending = false;
440  }
441
442   //----------------------------------------------------------------
443
444   void CField::setRelFile(CFile* _file)
445   {
446      this->file = _file;
447      hasOutputFile = true;
448   }
449
450   //----------------------------------------------------------------
451
452   StdString CField::GetName(void)    { return StdString("field"); }
453   StdString CField::GetDefName(void) { return CField::GetName(); }
454   ENodeType CField::GetType(void)    { return eField; }
455
456   //----------------------------------------------------------------
457
458   CGrid* CField::getRelGrid(void) const
459   {
460      return this->grid;
461   }
462
463   //----------------------------------------------------------------
464
465   CFile* CField::getRelFile(void) const
466   {
467      return this->file;
468   }
469
470   StdSize CField::getNStep(void) const
471   {
472      return this->nstep;
473   }
474
475   void CField::incrementNStep(void)
476   {
477      this->nstep++;
478   }
479
480   void CField::resetNStep(void)
481   {
482      this->nstep = 0;
483   }
484
485   void CField::resetNStepMax(void)
486   {
487      this->nstepMax = 0;
488   }
489
490   //----------------------------------------------------------------
491
492   const CDuration& CField::getFreqOperation(void) const
493   {
494      return this->freq_operation;
495   }
496
497   //----------------------------------------------------------------
498
499   const CDuration& CField::getFreqWrite(void) const
500   {
501      return this->freq_write;
502   }
503
504   //----------------------------------------------------------------
505
506   boost::shared_ptr<func::CFunctor> CField::getFieldOperation(void) const
507   {
508      return this->foperation;
509   }
510
511   bool CField::isActive(void) const
512   {
513      return !this->refObject.empty();
514   }
515
516   //----------------------------------------------------------------
517
518   CArray<double, 1> CField::getData(void) const
519   {
520      return(this->data);
521   }
522
523   //----------------------------------------------------------------
524
525   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
526   {
527      return(this->last_Write);
528   }
529
530   //----------------------------------------------------------------
531
532   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
533   {
534      return(this->last_operation);
535   }
536
537   void CField::solveAllReferenceEnabledField(bool doSending2Sever)
538   {
539     CContext* context = CContext::getCurrent();
540     if (!areAllReferenceSolved)
541     {
542        areAllReferenceSolved = true;
543        if (context->hasClient)
544        {
545          solveRefInheritance(true);
546          solveBaseReference();
547        }
548
549        solveOperation();
550        solveGridReference();
551     }
552     solveGridDomainAxisRef(doSending2Sever);
553     if (context->hasClient)
554     {
555       solveTransformedGrid();
556     }
557     solveCheckMaskIndex(doSending2Sever);
558   }
559
560   std::map<int, StdSize> CField::getGridDataSize()
561   {
562     return grid->getConnectedServerDataSize();
563   }
564
565   void CField::buildAllExpressionEnabledField()
566   {
567     if (!areAllReferenceSolved) solveAllReferenceEnabledField(true);
568     if (!areAllExpressionBuilt)
569     {
570       areAllExpressionBuilt = true;
571       if (hasDirectFieldReference() && (grid_ref.isEmpty())) baseRefObject->buildAllExpressionEnabledField();
572       buildExpression();
573       active = true;
574     }
575   }
576
577   //----------------------------------------------------------------
578
579   void  CField::solveOperation(void)
580   {
581      using namespace func;
582
583      if (!hasOutputFile && !hasFieldOut) return;
584
585      StdString id;
586      if (hasId()) id = getId();
587      else if (!name.isEmpty()) id = name;
588      else if (hasDirectFieldReference()) id = baseRefObject->getId();
589
590      CContext* context = CContext::getCurrent();
591
592      if (freq_op.isEmpty()) freq_op.setValue(TimeStep);
593
594      if (operation.isEmpty())
595      {
596         ERROR("CField::solveOperation(void)",
597               << "[ id = " << id << "]"
598               << "Impossible to define an operation for this field !");
599      }
600
601      if (freq_offset.isEmpty())
602        freq_offset.setValue(NoneDu);
603
604//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
605      if (context->hasServer)
606      {
607         if (hasOutputFile)
608         {
609           this->freq_operation_srv = this->file->output_freq.getValue();
610           this->freq_write_srv = this->file->output_freq.getValue();
611         }
612         this->lastlast_Write_srv = boost::shared_ptr<CDate>
613                        (new CDate(context->getCalendar()->getInitDate()));
614         this->last_Write_srv     = boost::shared_ptr<CDate>
615                        (new CDate(context->getCalendar()->getInitDate()));
616         this->last_operation_srv = boost::shared_ptr<CDate>
617                        (new CDate(context->getCalendar()->getInitDate()));
618//         this->foperation_srv     =
619//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
620
621         if (hasOutputFile)
622         {
623           const CDuration toffset = this->freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
624           *this->last_operation_srv   = *this->last_operation_srv - toffset;
625         }
626      }
627
628//      if (context->hasClient)
629//      {
630         this->freq_operation = freq_op.getValue();
631         if (hasOutputFile) this->freq_write = this->file->output_freq.getValue();
632         if (hasFieldOut)
633         {
634           this->freq_write = this->fieldOut->freq_op.getValue();
635         }
636         this->last_Write     = boost::shared_ptr<CDate>
637                        (new CDate(context->getCalendar()->getInitDate()));
638         this->last_operation = boost::shared_ptr<CDate>
639                        (new CDate(context->getCalendar()->getInitDate()));
640
641         const CDuration toffset = this->freq_operation - freq_offset.getValue() - context->getCalendar()->getTimeStep();
642         *this->last_operation   = *this->last_operation - toffset;
643
644         lastDataRequestedFromServer.setRelCalendar(*context->getCalendar());
645
646        if (operation.get() == "once") isOnceOperation = true;
647        else isOnceOperation = false;
648        isFirstOperation = true;
649
650#define DECLARE_FUNCTOR(MType, mtype) \
651   if (operation.getValue().compare(#mtype) == 0) \
652   { \
653      if (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true) \
654      { \
655        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data,default_value)); \
656        this->foperation = foperation_; \
657      } \
658      else \
659      { \
660        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
661        this->foperation = foperation_; \
662      } \
663      return; \
664   }
665
666#include "functor_type.conf"
667
668         ERROR("CField::solveOperation(void)",
669               << "[ operation = " << operation.getValue() << "]"
670               << "The operation is not defined !");
671//      }
672   }
673
674   //----------------------------------------------------------------
675/*
676   void CField::fromBinary(StdIStream& is)
677   {
678      SuperClass::fromBinary(is);
679#define CLEAR_ATT(name_)\
680      SuperClassAttribute::operator[](#name_)->reset()
681
682         CLEAR_ATT(domain_ref);
683         CLEAR_ATT(axis_ref);
684#undef CLEAR_ATT
685
686   }
687*/
688   //----------------------------------------------------------------
689
690   void CField::solveGridReference(void)
691   {
692      CDomain* domain;
693      CAxis* axis;
694      std::vector<CDomain*> vecDom;
695      std::vector<CAxis*> vecAxis;
696      std::vector<std::string> domList, axisList;
697
698      if (!domain_ref.isEmpty())
699      {
700         if (CDomain::has(domain_ref.getValue()))
701         {
702           domain = CDomain::get(domain_ref.getValue());
703           vecDom.push_back(domain);
704         }
705         else
706            ERROR("CField::solveGridReference(void)",
707                  << "Reference to the domain \'"
708                  << domain_ref.getValue() << "\' is wrong");
709      }
710
711      if (!axis_ref.isEmpty())
712      {
713         if (CAxis::has(axis_ref.getValue()))
714         {
715           axis = CAxis::get(axis_ref.getValue());
716           vecAxis.push_back(axis);
717         }
718         else
719            ERROR("CField::solveGridReference(void)",
720                  << "Reference to the axis \'"
721                  << axis_ref.getValue() <<"\' is wrong");
722      }
723
724      if (!grid_ref.isEmpty())
725      {
726         if (CGrid::has(grid_ref.getValue()))
727         {
728           this->grid = CGrid::get(grid_ref.getValue());
729           domList = grid->getDomainList();
730           axisList = grid->getAxisList();
731           if (domList.empty() && axisList.empty())
732           {
733             this->grid = CGrid::createGrid(vecDom, vecAxis);
734           }
735         }
736         else
737            ERROR("CField::solveGridReference(void)",
738                  << "Reference to the grid \'"
739                  << grid_ref.getValue() << "\' is wrong");
740      }
741      else
742      {
743         this->grid = CGrid::createGrid(vecDom, vecAxis);
744      }
745
746      if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty())
747      {
748            ERROR("CField::solveGridReference(void)",
749                  << "At least one dimension must be defined for this field.");
750      }
751   }
752
753   void CField::solveGridDomainAxisRef(bool checkAtt)
754   {
755     grid->solveDomainAxisRef(checkAtt);
756   }
757
758   void CField::solveCheckMaskIndex(bool doSendingIndex)
759   {
760     grid->checkMaskIndex(doSendingIndex);
761   }
762
763   CGrid* CField::getGridRefOfBaseReference()
764   {
765     solveRefInheritance(true);
766     solveBaseReference();
767     baseRefObject->solveGridReference();
768
769     return baseRefObject->grid;
770   }
771
772   void CField::solveTransformedGrid()
773   {
774     if (!grid_ref.isEmpty() && (!field_ref.isEmpty()))
775     {
776       CField* fieldRef  = this;
777       CGrid* gridRefOfFieldRef = 0;
778       while (fieldRef->hasDirectFieldReference())
779       {
780         if ((!(fieldRef->grid_ref.isEmpty())) &&
781             (fieldRef->grid_ref.getValue() != grid_ref.getValue()))
782         {
783           gridRefOfFieldRef = fieldRef->getGridRefOfBaseReference();
784           fieldRef->addReference(this);
785           fieldRef->solveGridDomainAxisRef(false);
786//           fieldRef->solveCheckMaskIndex(false);
787           break;
788         }
789         CField* tmp = fieldRef->getDirectFieldReference();
790         fieldRef = tmp;
791       }
792
793       if ((0 == gridRefOfFieldRef) &&
794           (!(fieldRef->grid_ref.isEmpty())) &&
795           (fieldRef->grid_ref.getValue() != grid_ref.getValue()))
796       {
797         gridRefOfFieldRef = fieldRef->getGridRefOfBaseReference();
798         fieldRef->addReference(this);
799         fieldRef->solveGridDomainAxisRef(false);
800//         fieldRef->solveCheckMaskIndex(false);
801       }
802
803       CGrid* relGridRef = CGrid::get(grid_ref.getValue());
804       if ((0 != gridRefOfFieldRef) && (relGridRef != gridRefOfFieldRef) && (!(relGridRef->isTransformed())))
805       {
806         gridRefOfFieldRef->transformGrid(relGridRef);
807         filterSources_.push_back(fieldRef);
808       }
809     }
810   }
811
812   const std::vector<CField*>& CField::getFilterSources()
813   {
814     return filterSources_;
815   }
816
817   void CField::applyFilter(const CArray<double, 1>& dataToSend, CArray<double,1>& dataToReceive)
818   {
819     std::vector<CField*>::iterator  itFilterSrc, iteFilterSrc;
820     if (!filterSources_.empty())
821     {
822        itFilterSrc = filterSources_.begin(); iteFilterSrc = filterSources_.end();
823        for (; itFilterSrc != iteFilterSrc; ++itFilterSrc)
824        {
825          if (0 != (*itFilterSrc)->grid->getTransformations())
826          {
827             const std::map<int, CArray<int,1>* >& localIndexToSend = (*itFilterSrc)->grid->getTransformations()->getLocalIndexToSendFromGridSource();
828             const std::map<int, std::vector<CArray<int,1>* > > localIndexToReceive = (*itFilterSrc)->grid->getTransformations()->getLocalIndexToReceiveOnGridDest();
829
830             sendAndReceiveTransformedData(localIndexToSend, dataToSend,
831                                           localIndexToReceive, dataToReceive);
832          }
833
834        }
835     }
836   }
837
838   void CField::sendAndReceiveTransformedData(const std::map<int, CArray<int,1>* >& localIndexToSend,
839                                              const CArray<double, 1>& dataSrc,
840                                              const std::map<int, std::vector<CArray<int,1>* > >& localIndexToReceive,
841                                              CArray<double,1>& dataDest)
842   {
843     CContext* context = CContext::getCurrent();
844     CContextClient* client=context->client;
845
846     // Sending data from field sources to do transformations
847     std::map<int, CArray<int,1>* >::const_iterator itbSend = localIndexToSend.begin(), itSend,
848                                                    iteSend = localIndexToSend.end();
849     int sendBuffSize = 0;
850     for (itSend = itbSend; itSend != iteSend; ++itSend) sendBuffSize = (sendBuffSize < (itSend->second)->numElements())
851                                                                        ? (itSend->second)->numElements(): sendBuffSize;
852     double* sendBuff;
853     if (0 != sendBuffSize) sendBuff = new double [sendBuffSize];
854     for (itSend = itbSend; itSend != iteSend; ++itSend)
855     {
856       int destRank = itSend->first;
857       CArray<int,1>* localIndex_p = itSend->second;
858       int countSize = localIndex_p->numElements();
859       std::cout << "Data Source " <<  dataSrc <<  std::endl;
860       for (int idx = 0; idx < countSize; ++idx)
861       {
862         sendBuff[idx] = dataSrc((*localIndex_p)(idx));
863       }
864       MPI_Send(sendBuff, countSize, MPI_DOUBLE, destRank, 12, client->intraComm);
865     }
866
867     // Receiving data on destination fields
868     std::map<int, std::vector<CArray<int,1>* > >::const_iterator itbRecv = localIndexToReceive.begin(), itRecv,
869                                                                  iteRecv = localIndexToReceive.end();
870     int recvBuffSize = 0;
871     for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv) recvBuffSize = (recvBuffSize < (itRecv->second).size())
872                                                                        ? (itRecv->second).size() : recvBuffSize;
873     double* recvBuff;
874     if (0 != recvBuffSize) recvBuff = new double [recvBuffSize];
875     for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
876     {
877       MPI_Status status;
878       int srcRank = itRecv->first;
879       int countSize = (itRecv->second).size();
880       MPI_Recv(recvBuff, recvBuffSize, MPI_DOUBLE, srcRank, 12, client->intraComm, &status);
881       for (int idx = 0; idx < countSize; ++idx)
882       {
883         CArray<int,1>* localIndex_p = (itRecv->second)[idx];
884         int numIndex = localIndex_p->numElements();
885         for (int i = 0; i < numIndex; ++i)
886         {
887           dataDest((*localIndex_p)(i)) = recvBuff[idx];
888         }
889       }
890       std::cout << "Data Destination " <<  dataDest <<  std::endl;
891     }
892
893     if (0 != sendBuffSize) delete [] sendBuff;
894     if (0 != recvBuffSize) delete [] recvBuff;
895   }
896
897   ///-------------------------------------------------------------------
898
899   template <>
900   void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
901   {
902      if (this->group_ref.isEmpty()) return;
903      StdString gref = this->group_ref.getValue();
904
905      if (!CFieldGroup::has(gref))
906         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
907               << "[ gref = " << gref << "]"
908               << " invalid group name !");
909
910      CFieldGroup* group = CFieldGroup::get(gref);
911      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
912
913      std::vector<CField*> allChildren  = group->getAllChildren();
914      std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end();
915
916      for (; it != end; it++)
917      {
918         CField* child = *it;
919         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId());
920
921      }
922   }
923
924   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
925   {
926     map<int, CArray<double,1>* >::iterator it;
927     for (it = data_srv.begin(); it != data_srv.end(); it++) *it->second = (*it->second - addOffset) / scaleFactor;
928   }
929
930   void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset)
931   {
932     map<int, CArray<double,1>* >::iterator it;
933     for (it = data_srv.begin(); it != data_srv.end(); it++) *it->second = *it->second * scaleFactor + addOffset;
934   }
935
936   void CField::outputField(CArray<double,3>& fieldOut)
937   {
938      map<int, CArray<double,1>* >::iterator it;
939      for (it = data_srv.begin(); it != data_srv.end(); it++)
940      {
941        grid->outputField(it->first,*it->second, fieldOut.dataFirst());
942      }
943   }
944
945   void CField::outputField(CArray<double,2>& fieldOut)
946   {
947      map<int, CArray<double,1>* >::iterator it;
948      for(it=data_srv.begin();it!=data_srv.end();it++)
949      {
950         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
951      }
952   }
953
954   void CField::outputField(CArray<double,1>& fieldOut)
955   {
956      map<int, CArray<double,1>* >::iterator it;
957
958      for (it = data_srv.begin(); it != data_srv.end(); it++)
959      {
960         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
961      }
962   }
963
964   void CField::inputField(CArray<double,3>& fieldOut)
965   {
966      map<int, CArray<double,1>*>::iterator it;
967      for (it = data_srv.begin(); it != data_srv.end(); it++)
968      {
969        grid->inputField(it->first, fieldOut.dataFirst(), *it->second);
970      }
971   }
972
973   void CField::inputField(CArray<double,2>& fieldOut)
974   {
975      map<int, CArray<double,1>*>::iterator it;
976      for(it = data_srv.begin(); it != data_srv.end(); it++)
977      {
978         grid->inputField(it->first, fieldOut.dataFirst(), *it->second);
979      }
980   }
981
982   void CField::inputField(CArray<double,1>& fieldOut)
983   {
984      map<int, CArray<double,1>*>::iterator it;
985      for (it = data_srv.begin(); it != data_srv.end(); it++)
986      {
987         grid->inputField(it->first, fieldOut.dataFirst(), *it->second);
988      }
989   }
990
991   ///-------------------------------------------------------------------
992
993   void CField::parse(xml::CXMLNode& node)
994   {
995      SuperClass::parse(node);
996      if (!node.getContent(this->content))
997      {
998        if (node.goToChildElement())
999        {
1000          do
1001          {
1002            if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node);
1003          } while (node.goToNextElement());
1004          node.goToParentElement();
1005        }
1006      }
1007    }
1008
1009  CArray<double,1>* CField::getInstantData(void)
1010  {
1011    if (!hasInstantData)
1012    {
1013      instantData.resize(grid->storeIndex_client.numElements());
1014      hasInstantData = true;
1015    }
1016    return &instantData;
1017  }
1018
1019  void CField::addDependency(CField* field, int slotId)
1020  {
1021    fieldDependency.push_back(pair<CField*,int>(field,slotId));
1022  }
1023
1024  void CField::buildExpression(void)
1025  {
1026    if (content.size() > 0)
1027    {
1028      CSimpleNodeExpr* simpleExpr = parseExpr(content+'\0');
1029      expression = CFieldNode::newNode(simpleExpr);
1030      delete simpleExpr;
1031      set<string> instantFieldIds;
1032      map<string,CField*> associatedInstantFieldIds;
1033      expression->getInstantFieldIds(instantFieldIds);
1034      for (set<string>::iterator it = instantFieldIds.begin(); it != instantFieldIds.end(); ++it)
1035      {
1036        if (*it != "this")
1037        {
1038          if (CField::has(*it))
1039          {
1040            CField* field = CField::get(*it);
1041//            field->processEnabledField();
1042            field->buildAllExpressionEnabledField();
1043            associatedInstantFieldIds[*it] = field;
1044          }
1045          else  ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
1046        }
1047      }
1048
1049      set<string> averageFieldIds;
1050      map<string,CField*> associatedAverageFieldIds;
1051
1052      expression->getAverageFieldIds(averageFieldIds);
1053      for (set<string>::iterator it = averageFieldIds.begin(); it != averageFieldIds.end(); ++it)
1054      {
1055        if (CField::has(*it))
1056        {
1057           CFieldGroup* root = CFieldGroup::get("field_definition");
1058           CField* averageField = root->createChild();
1059           CField* instantField = root->createChild();
1060           averageField->field_ref = *it;
1061           averageField->hasFieldOut = true;
1062           averageField->fieldOut = instantField;
1063           instantField->freq_op = freq_op;
1064//           averageField-> processEnabledField();
1065           averageField->buildAllExpressionEnabledField();
1066           instantField->SuperClassAttribute::setAttributes(averageField, true);
1067           instantField->field_ref.reset();
1068           instantField->operation.reset();
1069
1070//           instantField-> processEnabledField();
1071           instantField->buildAllExpressionEnabledField();
1072           associatedAverageFieldIds[*it] = instantField;
1073        }
1074        else ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
1075      }
1076
1077      expression->reduce(this,associatedInstantFieldIds,associatedAverageFieldIds);
1078
1079      slots.resize(instantFieldIds.size() + averageFieldIds.size());
1080      resetSlots();
1081      int slotId = 0;
1082      set<CField*> fields;
1083      expression->getFields(fields);
1084      for (set<CField*>::iterator it = fields.begin(); it != fields.end(); ++it, ++slotId) (*it)->addDependency(this,slotId);
1085      hasExpression = true;
1086    }
1087  }
1088
1089  void CField::resetSlots(void)
1090  {
1091    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) *it = false;
1092  }
1093
1094  bool CField::slotsFull(void)
1095  {
1096    bool ret = true;
1097    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) ret &= *it;
1098    return ret;
1099  }
1100
1101  void CField::setSlot(int slotId)
1102  {
1103    CContext* context = CContext::getCurrent();
1104    const CDate& currDate = context->getCalendar()->getCurrentDate();
1105    if (slotUpdateDate == NULL || currDate != *slotUpdateDate)
1106    {
1107      resetSlots();
1108      if (slotUpdateDate == NULL) slotUpdateDate = new CDate(currDate);
1109      else *slotUpdateDate = currDate;
1110    }
1111    slots[slotId] = true;
1112    if (slotsFull())
1113    {
1114      CArray<double,1> expr(expression->compute());
1115
1116      if (hasInstantData)
1117      {
1118        instantData = expr;
1119        for (list< pair<CField *,int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it)
1120          if (it->first != this) it->first->setSlot(it->second);
1121      }
1122
1123      if (hasOutputFile) updateDataFromExpression(expr);
1124
1125      const std::vector<CField*>& refField = getAllReference();
1126      for (std::vector<CField*>::const_iterator it = refField.begin(); it != refField.end(); it++)
1127      {
1128        if (!(*it)->hasExpression)
1129          (*it)->setDataFromExpression(expr);
1130      }
1131    }
1132  }
1133
1134   /*!
1135     This function retrieves Id of corresponding domain_ref and axis_ref (if any)
1136   of a field. In some cases, only domain exists but axis doesn't
1137   \return pair of Domain and Axis id
1138   */
1139   const std::pair<StdString,StdString>& CField::getRefDomainAxisIds()
1140   {
1141     CGrid* cgPtr = getRelGrid();
1142     if (NULL != cgPtr)
1143     {
1144       std::vector<StdString>::iterator it;
1145       if (!domain_ref.isEmpty())
1146       {
1147         std::vector<StdString> domainList = cgPtr->getDomainList();
1148         it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue());
1149         if (domainList.end() != it) domAxisIds_.first = *it;
1150       }
1151
1152       if (!axis_ref.isEmpty())
1153       {
1154         std::vector<StdString> axisList = cgPtr->getAxisList();
1155         it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue());
1156         if (axisList.end() != it) domAxisIds_.second = *it;
1157       }
1158     }
1159     return (domAxisIds_);
1160   }
1161
1162   CVariable* CField::addVariable(const string& id)
1163   {
1164     return vVariableGroup->createChild(id);
1165   }
1166
1167   CVariableGroup* CField::addVariableGroup(const string& id)
1168   {
1169     return vVariableGroup->createChildGroup(id);
1170   }
1171
1172   void CField::sendAddAllVariables()
1173   {
1174     if (!getAllVariables().empty())
1175     {
1176       // Firstly, it's necessary to add virtual variable group
1177       sendAddVariableGroup(getVirtualVariableGroup()->getId());
1178
1179       // Okie, now we can add to this variable group
1180       std::vector<CVariable*> allVar = getAllVariables();
1181       std::vector<CVariable*>::const_iterator it = allVar.begin();
1182       std::vector<CVariable*>::const_iterator itE = allVar.end();
1183
1184       for (; it != itE; ++it)
1185       {
1186         this->sendAddVariable((*it)->getId());
1187         (*it)->sendAllAttributesToServer();
1188         (*it)->sendValue();
1189       }
1190     }
1191   }
1192
1193   void CField::sendAddVariable(const string& id)
1194   {
1195    CContext* context = CContext::getCurrent();
1196
1197    if (!context->hasServer)
1198    {
1199       CContextClient* client = context->client;
1200
1201       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
1202       if (client->isServerLeader())
1203       {
1204         CMessage msg;
1205         msg << this->getId();
1206         msg << id;
1207         const std::list<int>& ranks = client->getRanksServerLeader();
1208         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1209           event.push(*itRank,1,msg);
1210         client->sendEvent(event);
1211       }
1212       else client->sendEvent(event);
1213    }
1214   }
1215
1216   void CField::sendAddVariableGroup(const string& id)
1217   {
1218    CContext* context = CContext::getCurrent();
1219    if (!context->hasServer)
1220    {
1221       CContextClient* client = context->client;
1222
1223       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP);
1224       if (client->isServerLeader())
1225       {
1226         CMessage msg;
1227         msg << this->getId();
1228         msg << id;
1229         const std::list<int>& ranks = client->getRanksServerLeader();
1230         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1231           event.push(*itRank,1,msg);
1232         client->sendEvent(event);
1233       }
1234       else client->sendEvent(event);
1235    }
1236   }
1237
1238   void CField::recvAddVariable(CEventServer& event)
1239   {
1240
1241      CBufferIn* buffer = event.subEvents.begin()->buffer;
1242      string id;
1243      *buffer >> id;
1244      get(id)->recvAddVariable(*buffer);
1245   }
1246
1247   void CField::recvAddVariable(CBufferIn& buffer)
1248   {
1249      string id;
1250      buffer >> id;
1251      addVariable(id);
1252   }
1253
1254   void CField::recvAddVariableGroup(CEventServer& event)
1255   {
1256
1257      CBufferIn* buffer = event.subEvents.begin()->buffer;
1258      string id;
1259      *buffer >> id;
1260      get(id)->recvAddVariableGroup(*buffer);
1261   }
1262
1263   void CField::recvAddVariableGroup(CBufferIn& buffer)
1264   {
1265      string id;
1266      buffer >> id;
1267      addVariableGroup(id);
1268   }
1269
1270   DEFINE_REF_FUNC(Field,field)
1271
1272//  void CField::addReference(CField* field)
1273//  {
1274//    refObject.push_back(field);
1275//  }
1276//
1277//   //----------------------------------------------------------------
1278//
1279//   bool CField::hasDirectFieldReference(void) const
1280//   {
1281//     return !this->field_ref.isEmpty();
1282//   }
1283//
1284//   //----------------------------------------------------------------
1285//
1286//   const StdString& CField::getBaseFieldId(void) const
1287//   {
1288//      return this->getBaseFieldReference()->getId();
1289//   }
1290//
1291//   //----------------------------------------------------------------
1292//
1293//   /*!
1294//   \brief Get pointer to direct field to which the current field refers.
1295//   */
1296//   CField* CField::getDirectFieldReference(void) const
1297//   {
1298//      if (this->field_ref.isEmpty())
1299//         return this->getBaseFieldReference();
1300//
1301//      if (!CField::has(this->field_ref.getValue()))
1302//         ERROR("CField::getDirectFieldReference(void)",
1303//               << "[ ref_name = " << this->field_ref.getValue() << "]"
1304//               << " invalid field name !");
1305//
1306//      return CField::get(this->field_ref.getValue());
1307//   }
1308//
1309//   //----------------------------------------------------------------
1310//
1311//   CField* CField::getBaseFieldReference(void) const
1312//   {
1313//      return baseRefObject;
1314//   }
1315//
1316//   //----------------------------------------------------------------
1317//
1318//   const std::vector<CField*>& CField::getAllReference(void) const
1319//   {
1320//      return refObject;
1321//   }
1322//
1323//   /*!
1324//   \brief Searching for all reference of a field
1325//   If a field refers to (an)other field(s), we will search for all its referenced parents.
1326//   Moreover, if any father, direct or indirect (e.g: two levels up), has non-empty attributes,
1327//   all its attributes will be added to the current field
1328//   \param [in] apply Flag to specify whether current field uses attributes of its father
1329//               in case the attribute is empty (true) or its attributes are replaced by ones of its father (false)
1330//   */
1331//   void CField::solveRefInheritance(bool apply)
1332//   {
1333//      std::set<CField *> sset;
1334//      CField* refer_sptr;
1335//      CField* refer_ptr = this;
1336//
1337//      while (refer_ptr->hasDirectFieldReference())
1338//      {
1339//         refer_sptr = refer_ptr->getDirectFieldReference();
1340//         refer_ptr  = refer_sptr;
1341//
1342//         if(sset.end() != sset.find(refer_ptr))
1343//         {
1344//            DEBUG (<< "Circular dependency stopped for field object on "
1345//                   << "\"" + refer_ptr->getId() + "\" !");
1346//            break;
1347//         }
1348//
1349//         SuperClassAttribute::setAttributes(refer_ptr, apply);
1350//         sset.insert(refer_ptr);
1351//      }
1352//   }
1353//
1354//   /*!
1355//   \brief Only on SERVER side. Remove all field_ref from current field
1356//   On creating a new field on server side, redundant "field_ref" is still kept in the attribute list
1357//   of the current field. This function removes this from current field
1358//   */
1359//   void CField::removeRefInheritance()
1360//   {
1361//     if (this->field_ref.isEmpty()) return;
1362//     this->clearAttribute("field_ref");
1363//   }
1364//
1365//   void CField::solveBaseReference(void)
1366//   {
1367//      std::set<CField *> sset;
1368//      CField* refer_sptr;
1369//      CField* refer_ptr = this;
1370//
1371//      if (this->hasDirectFieldReference())  baseRefObject = getDirectFieldReference();
1372//      else  baseRefObject = CField::get(this);
1373//
1374//      while (refer_ptr->hasDirectFieldReference())
1375//      {
1376//         refer_sptr = refer_ptr->getDirectFieldReference();
1377//         refer_ptr  = refer_sptr;
1378//
1379//         if(sset.end() != sset.find(refer_ptr))
1380//         {
1381//            DEBUG (<< "Circular dependency stopped for field object on "
1382//                   << "\"" + refer_ptr->getId() + "\" !");
1383//            break;
1384//         }
1385//
1386//         sset.insert(refer_ptr);
1387//      }
1388//
1389//      if (hasDirectFieldReference()) baseRefObject->addReference(this);
1390//   }
1391} // namespace xios
Note: See TracBrowser for help on using the repository browser.