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

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

Use the filter infrastructure to handle the temporal operations.

Add a temporal filter to do so.

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