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

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

Use the filter infrastructure to handle the spatial transformations.

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