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

Last change on this file since 642 was 642, checked in by rlacroix, 6 years ago

Use the filter infrastructure to handle the expressions

Parse the expressions to get a new tree representation that can be converted to a filter graph based on new arithmetic filters.

Temporal operations are still unsupported.

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