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
RevLine 
[219]1#include "field.hpp"
2
[352]3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
[219]6
7#include "node_type.hpp"
8#include "calendar_util.hpp"
[352]9#include "message.hpp"
[591]10#include "xios_spl.hpp"
[352]11#include "type.hpp"
[638]12#include "timer.hpp"
[352]13#include "context_client.hpp"
[586]14#include "context_server.hpp"
[459]15#include <set>
[640]16#include "garbage_collector.hpp"
17#include "source_filter.hpp"
18#include "store_filter.hpp"
19#include "file_writer_filter.hpp"
[641]20#include "pass_through_filter.hpp"
[642]21#include "filter_expr_node.hpp"
22#include "lex_parser.hpp"
[643]23#include "temporal_filter.hpp"
[219]24
[335]25namespace xios{
[509]26
[219]27   /// ////////////////////// Définitions ////////////////////// ///
28
29   CField::CField(void)
30      : CObjectTemplate<CField>(), CFieldAttributes()
31      , refObject(), baseRefObject()
32      , grid(), file()
33      , freq_operation(), freq_write()
[599]34      , nstep(0), nstepMax(0), isEOF(false)
[219]35      , last_Write(), last_operation()
[459]36      , foperation(), hasInstantData(false), hasExpression(false)
[460]37      , active(false) , hasOutputFile(false),hasFieldOut(false), slotUpdateDate(NULL)
[624]38      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false)
[598]39      , isReadDataRequestPending(false)
[624]40      , filterSources_()
[640]41   { setVirtualVariableGroup(); }
[219]42
[562]43   CField::CField(const StdString& id)
[219]44      : CObjectTemplate<CField>(id), CFieldAttributes()
45      , refObject(), baseRefObject()
46      , grid(), file()
47      , freq_operation(), freq_write()
[599]48      , nstep(0), nstepMax(0), isEOF(false)
[219]49      , last_Write(), last_operation()
[466]50      , foperation(), hasInstantData(false), hasExpression(false)
[460]51      , active(false), hasOutputFile(false), hasFieldOut(false), slotUpdateDate(NULL)
[624]52      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false)
[598]53      , isReadDataRequestPending(false)
[624]54      , filterSources_()
[562]55   { setVirtualVariableGroup(); }
[219]56
57   CField::~CField(void)
58   {
[562]59//      this->grid.reset();
60//      this->file.reset();
61      this->foperation.reset();
62      if (hasExpression) delete expression;
63      if (slotUpdateDate != NULL) delete slotUpdateDate;
[509]64
[219]65   }
66
[472]67
68  //----------------------------------------------------------------
69
70   void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
[509]71   {
72      this->vVariableGroup = newVVariableGroup;
[472]73   }
[509]74
[472]75   void CField::setVirtualVariableGroup(void)
76   {
77      this->setVirtualVariableGroup(CVariableGroup::create());
78   }
[509]79
[472]80   CVariableGroup* CField::getVirtualVariableGroup(void) const
81   {
[562]82      return this->vVariableGroup;
[472]83   }
84
[509]85
[472]86   std::vector<CVariable*> CField::getAllVariables(void) const
87   {
[562]88      return this->vVariableGroup->getAllChildren();
[472]89   }
[509]90
[562]91   void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent)
[472]92   {
[562]93      SuperClassAttribute::setAttributes(parent, apply);
[472]94      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
95   }
[219]96   //----------------------------------------------------------------
[472]97   //----------------------------------------------------------------
[219]98
99   bool CField::updateDataServer
[562]100      (const CDate& currDate,
[369]101       const std::deque< CArray<double, 1>* > storedClient)
[219]102   {
[343]103      const CDate opeDate      = *last_operation + freq_operation;
[509]104      const CDate writeDate    = *last_Write     + freq_write;
105
[278]106      if (opeDate <= currDate)
[219]107      {
[369]108         if (this->data.numElements() != this->grid->storeIndex[0]->numElements())
[278]109         {
[562]110            this->data.resize(this->grid->storeIndex[0]->numElements());
[509]111         }
[562]112         CArray<double,1> input(data.numElements());
[509]113         this->grid->inputFieldServer(storedClient, input);
[219]114         (*this->foperation)(input);
115         *last_operation = currDate;
116      }
[278]117      if (writeDate < (currDate + freq_operation))
[219]118      {
[278]119         this->foperation->final();
120         this->incrementNStep();
121         *last_Write = writeDate;
[562]122         return true;
[219]123      }
[562]124      return false;
[219]125   }
[509]126
[598]127  bool CField::dispatchEvent(CEventServer& event)
[300]128  {
[562]129    if (SuperClass::dispatchEvent(event)) return true;
[300]130    else
131    {
132      switch(event.type)
133      {
134        case EVENT_ID_UPDATE_DATA :
[562]135          recvUpdateData(event);
136          return true;
137          break;
[472]138
[598]139        case EVENT_ID_READ_DATA :
140          recvReadDataRequest(event);
141          return true;
142          break;
[509]143
[598]144        case EVENT_ID_READ_DATA_READY :
145          recvReadDataReady(event);
146          return true;
147          break;
[509]148
[598]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
[300]159        default :
[562]160          ERROR("bool CField::dispatchEvent(CEventServer& event)", << "Unknown Event");
161          return false;
[300]162      }
163    }
164  }
[509]165
[300]166  void CField::sendUpdateData(void)
167  {
[562]168    CContext* context = CContext::getCurrent();
169    CContextClient* client = context->client;
[509]170
[562]171    CEventClient event(getType(),EVENT_ID_UPDATE_DATA);
[509]172
[562]173    map<int,CArray<int, 1>* >::iterator it;
174    list<shared_ptr<CMessage> > list_msg;
175    list< CArray<double,1>* > list_data;
[509]176
[567]177    if (!grid->doGridHaveDataDistributed())
[300]178    {
[569]179       if (0 == client->clientRank)
[567]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);
[300]195    }
[567]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    }
[509]211
[562]212    for (list< CArray<double,1>* >::iterator it = list_data.begin(); it != list_data.end(); it++) delete *it;
[300]213  }
[509]214
[638]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
[300]271  void CField::recvUpdateData(CEventServer& event)
272  {
[562]273    vector<int> ranks;
274    vector<CBufferIn*> buffers;
[509]275
[562]276    list<CEventServer::SSubEvent>::iterator it;
277    string fieldId;
[219]278
[562]279    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
[300]280    {
[562]281      int rank = it->rank;
282      CBufferIn* buffer = it->buffer;
283      *buffer >> fieldId;
284      ranks.push_back(rank);
285      buffers.push_back(buffer);
[300]286    }
[562]287    get(fieldId)->recvUpdateData(ranks,buffers);
[300]288  }
[509]289
[300]290  void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
291  {
292    if (data_srv.empty())
293    {
[562]294      for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
[300]295      {
[562]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]300      }
301    }
302
[562]303    CContext* context = CContext::getCurrent();
304    const CDate& currDate = context->getCalendar()->getCurrentDate();
[343]305    const CDate opeDate      = *last_operation_srv + freq_operation_srv;
[509]306    const CDate writeDate    = *last_Write_srv     + freq_write_srv;
[300]307
308    if (opeDate <= currDate)
309    {
[562]310      for (int n = 0; n < ranks.size(); n++)
[300]311      {
[562]312        CArray<double,1> data_tmp;
313        *buffers[n] >> data_tmp;
314        (*foperation_srv[ranks[n]])(data_tmp);
[300]315      }
316      *last_operation_srv = currDate;
317    }
[509]318
[300]319    if (writeDate < (currDate + freq_operation_srv))
320    {
[562]321      for (int n = 0; n < ranks.size(); n++)
[300]322      {
323        this->foperation_srv[ranks[n]]->final();
324      }
[509]325
[300]326      *last_Write_srv = writeDate;
[562]327      writeField();
328      *lastlast_Write_srv = *last_Write_srv;
[300]329    }
330  }
[509]331
[300]332  void CField::writeField(void)
333  {
[562]334    if (!getRelFile()->allDomainEmpty)
[586]335    {
[599]336      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
[379]337      {
338        getRelFile()->checkFile();
339        this->incrementNStep();
340        getRelFile()->getDataOutput()->writeFieldData(CField::get(this));
341      }
[586]342    }
[300]343  }
[562]344
[598]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
[599]398    bool hasData = readField();
[598]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();
[599]405      msg << getId();
406      if (hasData)
407        msg << getNStep() - 1 << *it->second;
408      else
[603]409        msg << size_t(-1);
[598]410      event.push(it->first, grid->nbSenders[it->first], msg);
411    }
412    client->sendEvent(event);
[599]413  }
[598]414
[599]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;
[598]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;
[640]466    std::map<int, CArray<double,1> > data;
467
[598]468    for (int i = 0; i < ranks.size(); i++)
469    {
470      int rank = ranks[i];
[599]471      *buffers[i] >> record;
[603]472      isEOF = (record == size_t(-1));
[598]473
[599]474      if (!isEOF)
[640]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)
[599]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;
[598]501    }
502
[599]503    if (!isEOF)
[598]504    {
[599]505      for (list< pair<CField*, int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it)
506        it->first->setSlot(it->second);
[598]507
[599]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      }
[640]516    }*/
[598]517
518    isReadDataRequestPending = false;
519  }
520
[219]521   //----------------------------------------------------------------
522
[347]523   void CField::setRelFile(CFile* _file)
[509]524   {
[459]525      this->file = _file;
[562]526      hasOutputFile = true;
[219]527   }
528
529   //----------------------------------------------------------------
530
[562]531   StdString CField::GetName(void)    { return StdString("field"); }
532   StdString CField::GetDefName(void) { return CField::GetName(); }
533   ENodeType CField::GetType(void)    { return eField; }
[219]534
535   //----------------------------------------------------------------
536
[347]537   CGrid* CField::getRelGrid(void) const
[509]538   {
[562]539      return this->grid;
[219]540   }
541
542   //----------------------------------------------------------------
543
[347]544   CFile* CField::getRelFile(void) const
[509]545   {
[562]546      return this->file;
[219]547   }
[509]548
[266]549   StdSize CField::getNStep(void) const
550   {
[562]551      return this->nstep;
[266]552   }
[509]553
[266]554   void CField::incrementNStep(void)
555   {
556      this->nstep++;
557   }
[509]558
[321]559   void CField::resetNStep(void)
560   {
[562]561      this->nstep = 0;
[321]562   }
[219]563
[599]564   void CField::resetNStepMax(void)
565   {
566      this->nstepMax = 0;
567   }
568
[219]569   //----------------------------------------------------------------
570
[562]571   const CDuration& CField::getFreqOperation(void) const
[219]572   {
[562]573      return this->freq_operation;
[219]574   }
[509]575
[219]576   //----------------------------------------------------------------
[562]577
578   const CDuration& CField::getFreqWrite(void) const
[219]579   {
[562]580      return this->freq_write;
[219]581   }
[509]582
[219]583   //----------------------------------------------------------------
[509]584
[219]585   boost::shared_ptr<func::CFunctor> CField::getFieldOperation(void) const
586   {
[562]587      return this->foperation;
[219]588   }
589
[310]590   bool CField::isActive(void) const
[509]591   {
[562]592      return !this->refObject.empty();
[310]593   }
[562]594
[219]595   //----------------------------------------------------------------
[509]596
[369]597   CArray<double, 1> CField::getData(void) const
[219]598   {
599      return(this->data);
600   }
601
602   //----------------------------------------------------------------
603
[343]604   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
[219]605   {
606      return(this->last_Write);
607   }
608
609   //----------------------------------------------------------------
610
[343]611   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
[219]612   {
613      return(this->last_operation);
614   }
615
[641]616   //----------------------------------------------------------------
617
618   boost::shared_ptr<COutputPin> CField::getInstantDataFilter()
619   {
620     return instantDataFilter;
621   }
622
623   //----------------------------------------------------------------
624
[509]625   void CField::solveAllReferenceEnabledField(bool doSending2Sever)
[459]626   {
[509]627     CContext* context = CContext::getCurrent();
628     if (!areAllReferenceSolved)
629     {
630        areAllReferenceSolved = true;
[510]631        if (context->hasClient)
[509]632        {
633          solveRefInheritance(true);
634          solveBaseReference();
635        }
[478]636
[509]637        solveOperation();
638        solveGridReference();
639     }
640     solveGridDomainAxisRef(doSending2Sever);
[619]641     if (context->hasClient)
642     {
643       solveTransformedGrid();
644     }
[623]645     solveCheckMaskIndex(doSending2Sever);
[509]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;
[619]659       if (hasDirectFieldReference() && (grid_ref.isEmpty())) baseRefObject->buildAllExpressionEnabledField();
[509]660       buildExpression();
[562]661       active = true;
[509]662     }
663   }
664
[219]665   //----------------------------------------------------------------
666
667   void  CField::solveOperation(void)
668   {
669      using namespace func;
[509]670
[640]671      CContext* context = CContext::getCurrent();
[509]672
[640]673      if (!context->hasServer || !hasOutputFile) return;
674
[562]675      StdString id;
676      if (hasId()) id = getId();
677      else if (!name.isEmpty()) id = name;
678      else if (hasDirectFieldReference()) id = baseRefObject->getId();
[509]679
[538]680      if (freq_op.isEmpty()) freq_op.setValue(TimeStep);
[509]681
[562]682      if (operation.isEmpty())
[219]683      {
684         ERROR("CField::solveOperation(void)",
685               << "[ id = " << id << "]"
[421]686               << "Impossible to define an operation for this field !");
[219]687      }
[509]688
[538]689      if (freq_offset.isEmpty())
690        freq_offset.setValue(NoneDu);
[219]691
[300]692//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
693      if (context->hasServer)
[219]694      {
[509]695         if (hasOutputFile)
[460]696         {
[538]697           this->freq_operation_srv = this->file->output_freq.getValue();
698           this->freq_write_srv = this->file->output_freq.getValue();
[460]699         }
[538]700         this->lastlast_Write_srv = boost::shared_ptr<CDate>
[343]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()));
[300]706//         this->foperation_srv     =
707//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
[509]708
709         if (hasOutputFile)
[460]710         {
[538]711           const CDuration toffset = this->freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
[460]712           *this->last_operation_srv   = *this->last_operation_srv - toffset;
713         }
[219]714      }
[509]715
[449]716//      if (context->hasClient)
[509]717//      {
[538]718         this->freq_operation = freq_op.getValue();
719         if (hasOutputFile) this->freq_write = this->file->output_freq.getValue();
[509]720         if (hasFieldOut)
[460]721         {
[538]722           this->freq_write = this->fieldOut->freq_op.getValue();
[460]723         }
[343]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()));
[509]728
[538]729         const CDuration toffset = this->freq_operation - freq_offset.getValue() - context->getCalendar()->getTimeStep();
[509]730         *this->last_operation   = *this->last_operation - toffset;
731
[598]732         lastDataRequestedFromServer.setRelCalendar(*context->getCalendar());
733
[562]734        if (operation.get() == "once") isOnceOperation = true;
735        else isOnceOperation = false;
736        isFirstOperation = true;
[509]737
[562]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) \
[470]742      { \
743        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data,default_value)); \
[473]744        this->foperation = foperation_; \
[470]745      } \
746      else \
747      { \
748        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
[562]749        this->foperation = foperation_; \
[470]750      } \
[562]751      return; \
[219]752   }
[509]753
[219]754#include "functor_type.conf"
[509]755
[219]756         ERROR("CField::solveOperation(void)",
757               << "[ operation = " << operation.getValue() << "]"
[421]758               << "The operation is not defined !");
[449]759//      }
[219]760   }
[509]761
[219]762   //----------------------------------------------------------------
[640]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   {
[641]774     if (!areAllReferenceSolved) solveAllReferenceEnabledField(false);
775
[640]776     // Start by building a filter which can provide the field's instant data
777     if (!instantDataFilter)
778     {
[642]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       }
[641]785       // Check if we have a reference on another field
[642]786       else if (!field_ref.isEmpty())
[641]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       }
[640]794       // Check if the data is to be read from a file
[641]795       else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read)
[640]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));
[643]813         getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0);
[640]814       }
815     }
816   }
817
[642]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
[643]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
[640]877   //----------------------------------------------------------------
[369]878/*
[562]879   void CField::fromBinary(StdIStream& is)
[219]880   {
881      SuperClass::fromBinary(is);
882#define CLEAR_ATT(name_)\
[369]883      SuperClassAttribute::operator[](#name_)->reset()
[219]884
885         CLEAR_ATT(domain_ref);
886         CLEAR_ATT(axis_ref);
887#undef CLEAR_ATT
888
889   }
[369]890*/
[219]891   //----------------------------------------------------------------
892
893   void CField::solveGridReference(void)
894   {
[347]895      CDomain* domain;
896      CAxis* axis;
[541]897      std::vector<CDomain*> vecDom;
898      std::vector<CAxis*> vecAxis;
[542]899      std::vector<std::string> domList, axisList;
[219]900
901      if (!domain_ref.isEmpty())
902      {
[346]903         if (CDomain::has(domain_ref.getValue()))
[541]904         {
[562]905           domain = CDomain::get(domain_ref.getValue());
[541]906           vecDom.push_back(domain);
907         }
[219]908         else
909            ERROR("CField::solveGridReference(void)",
[421]910                  << "Reference to the domain \'"
[562]911                  << domain_ref.getValue() << "\' is wrong");
[219]912      }
913
914      if (!axis_ref.isEmpty())
915      {
[346]916         if (CAxis::has(axis_ref.getValue()))
[541]917         {
[562]918           axis = CAxis::get(axis_ref.getValue());
[541]919           vecAxis.push_back(axis);
920         }
[219]921         else
922            ERROR("CField::solveGridReference(void)",
[421]923                  << "Reference to the axis \'"
[562]924                  << axis_ref.getValue() <<"\' is wrong");
[219]925      }
926
927      if (!grid_ref.isEmpty())
928      {
[346]929         if (CGrid::has(grid_ref.getValue()))
[541]930         {
[562]931           this->grid = CGrid::get(grid_ref.getValue());
[541]932           domList = grid->getDomainList();
933           axisList = grid->getAxisList();
[600]934           if (domList.empty() && axisList.empty())
[586]935           {
936             this->grid = CGrid::createGrid(vecDom, vecAxis);
937           }
[541]938         }
[219]939         else
940            ERROR("CField::solveGridReference(void)",
[421]941                  << "Reference to the grid \'"
942                  << grid_ref.getValue() << "\' is wrong");
[219]943      }
[586]944      else
945      {
946         this->grid = CGrid::createGrid(vecDom, vecAxis);
947      }
[509]948
[562]949      if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty())
[219]950      {
951            ERROR("CField::solveGridReference(void)",
[540]952                  << "At least one dimension must be defined for this field.");
953      }
[509]954   }
[459]955
[509]956   void CField::solveGridDomainAxisRef(bool checkAtt)
957   {
958     grid->solveDomainAxisRef(checkAtt);
[219]959   }
960
[509]961   void CField::solveCheckMaskIndex(bool doSendingIndex)
962   {
963     grid->checkMaskIndex(doSendingIndex);
964   }
[219]965
[619]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       {
[632]1007         relGridRef->transformGrid(gridRefOfFieldRef);
[619]1008         filterSources_.push_back(fieldRef);
1009       }
1010     }
1011   }
1012
1013   const std::vector<CField*>& CField::getFilterSources()
1014   {
1015     return filterSources_;
1016   }
1017
[620]1018   void CField::applyFilter(const CArray<double, 1>& dataToSend, CArray<double,1>& dataToReceive)
[619]1019   {
[620]1020     std::vector<CField*>::iterator  itFilterSrc, iteFilterSrc;
1021     if (!filterSources_.empty())
1022     {
1023        itFilterSrc = filterSources_.begin(); iteFilterSrc = filterSources_.end();
[630]1024        dataToReceive = 0.0; // Reset all data destination
[620]1025        for (; itFilterSrc != iteFilterSrc; ++itFilterSrc)
1026        {
[632]1027          if (0 != grid->getTransformations())
[620]1028          {
[632]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();
[621]1031
[620]1032             sendAndReceiveTransformedData(localIndexToSend, dataToSend,
1033                                           localIndexToReceive, dataToReceive);
1034          }
[619]1035
[620]1036        }
1037     }
[619]1038   }
1039
[620]1040   void CField::sendAndReceiveTransformedData(const std::map<int, CArray<int,1>* >& localIndexToSend,
1041                                              const CArray<double, 1>& dataSrc,
[630]1042                                              const std::map<int,std::vector<std::vector<std::pair<int,double> > > >& localIndexToReceive,
[620]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
[630]1069     std::map<int,std::vector<std::vector<std::pair<int,double> > > >::const_iterator itbRecv = localIndexToReceive.begin(), itRecv,
[620]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       {
[630]1084         const std::vector<std::pair<int,double> >& localIndex_p = (itRecv->second)[idx];
1085         int numIndex = localIndex_p.size();
[620]1086         for (int i = 0; i < numIndex; ++i)
1087         {
[630]1088//           if ((localIndex_p)[i].first >= dataDest.numElements() )
1089           dataDest((localIndex_p)[i].first) += recvBuff[idx] * ((localIndex_p)[i].second);
[620]1090         }
1091       }
1092     }
1093
1094     if (0 != sendBuffSize) delete [] sendBuff;
1095     if (0 != recvBuffSize) delete [] recvBuff;
1096   }
1097
[219]1098   ///-------------------------------------------------------------------
1099
1100   template <>
[562]1101   void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
[219]1102   {
1103      if (this->group_ref.isEmpty()) return;
1104      StdString gref = this->group_ref.getValue();
1105
[346]1106      if (!CFieldGroup::has(gref))
[219]1107         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
1108               << "[ gref = " << gref << "]"
1109               << " invalid group name !");
1110
[347]1111      CFieldGroup* group = CFieldGroup::get(gref);
1112      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
[219]1113
[347]1114      std::vector<CField*> allChildren  = group->getAllChildren();
[562]1115      std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end();
[509]1116
[219]1117      for (; it != end; it++)
1118      {
[347]1119         CField* child = *it;
[562]1120         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId());
[509]1121
[219]1122      }
1123   }
[509]1124
[464]1125   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
1126   {
1127     map<int, CArray<double,1>* >::iterator it;
[562]1128     for (it = data_srv.begin(); it != data_srv.end(); it++) *it->second = (*it->second - addOffset) / scaleFactor;
[464]1129   }
[509]1130
[599]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
[369]1137   void CField::outputField(CArray<double,3>& fieldOut)
[300]1138   {
[369]1139      map<int, CArray<double,1>* >::iterator it;
[562]1140      for (it = data_srv.begin(); it != data_srv.end(); it++)
[551]1141      {
[562]1142        grid->outputField(it->first,*it->second, fieldOut.dataFirst());
[551]1143      }
[300]1144   }
[509]1145
[369]1146   void CField::outputField(CArray<double,2>& fieldOut)
[300]1147   {
[369]1148      map<int, CArray<double,1>* >::iterator it;
[567]1149      for(it=data_srv.begin();it!=data_srv.end();it++)
1150      {
1151         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
1152      }
1153   }
[219]1154
[567]1155   void CField::outputField(CArray<double,1>& fieldOut)
1156   {
1157      map<int, CArray<double,1>* >::iterator it;
1158
[562]1159      for (it = data_srv.begin(); it != data_srv.end(); it++)
[300]1160      {
[567]1161         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
[300]1162      }
1163   }
[551]1164
[599]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
[219]1192   ///-------------------------------------------------------------------
1193
[562]1194   void CField::parse(xml::CXMLNode& node)
[459]1195   {
1196      SuperClass::parse(node);
[562]1197      if (!node.getContent(this->content))
[472]1198      {
[476]1199        if (node.goToChildElement())
[472]1200        {
[476]1201          do
1202          {
[562]1203            if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node);
1204          } while (node.goToNextElement());
[476]1205          node.goToParentElement();
1206        }
[472]1207      }
[459]1208    }
[509]1209
[459]1210  CArray<double,1>* CField::getInstantData(void)
1211  {
[509]1212    if (!hasInstantData)
[459]1213    {
[562]1214      instantData.resize(grid->storeIndex_client.numElements());
1215      hasInstantData = true;
[459]1216    }
[562]1217    return &instantData;
[459]1218  }
[509]1219
[459]1220  void CField::addDependency(CField* field, int slotId)
1221  {
[562]1222    fieldDependency.push_back(pair<CField*,int>(field,slotId));
[459]1223  }
[509]1224
[459]1225  void CField::buildExpression(void)
1226  {
[509]1227    if (content.size() > 0)
[459]1228    {
[642]1229      CSimpleNodeExpr* simpleExpr;// = parseExpr(content+'\0');
[562]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)
[460]1236      {
[562]1237        if (*it != "this")
[460]1238        {
[509]1239          if (CField::has(*it))
[460]1240          {
[562]1241            CField* field = CField::get(*it);
1242//            field->processEnabledField();
[509]1243            field->buildAllExpressionEnabledField();
[562]1244            associatedInstantFieldIds[*it] = field;
[460]1245          }
[562]1246          else  ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
[460]1247        }
1248      }
[509]1249
[562]1250      set<string> averageFieldIds;
1251      map<string,CField*> associatedAverageFieldIds;
[459]1252
[562]1253      expression->getAverageFieldIds(averageFieldIds);
1254      for (set<string>::iterator it = averageFieldIds.begin(); it != averageFieldIds.end(); ++it)
[509]1255      {
1256        if (CField::has(*it))
[460]1257        {
[562]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();
[509]1266           averageField->buildAllExpressionEnabledField();
[460]1267           instantField->SuperClassAttribute::setAttributes(averageField, true);
[562]1268           instantField->field_ref.reset();
1269           instantField->operation.reset();
[460]1270
[562]1271//           instantField-> processEnabledField();
[509]1272           instantField->buildAllExpressionEnabledField();
[562]1273           associatedAverageFieldIds[*it] = instantField;
[460]1274        }
[562]1275        else ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
[460]1276      }
1277
[562]1278      expression->reduce(this,associatedInstantFieldIds,associatedAverageFieldIds);
[460]1279
[562]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;
[459]1287    }
1288  }
[509]1289
[459]1290  void CField::resetSlots(void)
1291  {
[562]1292    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) *it = false;
[459]1293  }
[509]1294
[459]1295  bool CField::slotsFull(void)
1296  {
[562]1297    bool ret = true;
1298    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) ret &= *it;
1299    return ret;
[459]1300  }
1301
1302  void CField::setSlot(int slotId)
1303  {
[562]1304    CContext* context = CContext::getCurrent();
1305    const CDate& currDate = context->getCalendar()->getCurrentDate();
1306    if (slotUpdateDate == NULL || currDate != *slotUpdateDate)
[459]1307    {
[562]1308      resetSlots();
1309      if (slotUpdateDate == NULL) slotUpdateDate = new CDate(currDate);
1310      else *slotUpdateDate = currDate;
[459]1311    }
[562]1312    slots[slotId] = true;
[459]1313    if (slotsFull())
1314    {
[562]1315      CArray<double,1> expr(expression->compute());
[509]1316
1317      if (hasInstantData)
[459]1318      {
[562]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);
[459]1322      }
[509]1323
[562]1324      if (hasOutputFile) updateDataFromExpression(expr);
[509]1325
[562]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      }
[459]1332    }
1333  }
[472]1334
[509]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   */
[569]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       }
[472]1352
[569]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
[472]1363   CVariable* CField::addVariable(const string& id)
1364   {
[562]1365     return vVariableGroup->createChild(id);
[472]1366   }
1367
1368   CVariableGroup* CField::addVariableGroup(const string& id)
1369   {
[562]1370     return vVariableGroup->createChildGroup(id);
[472]1371   }
1372
[509]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
[472]1394   void CField::sendAddVariable(const string& id)
1395   {
[562]1396    CContext* context = CContext::getCurrent();
[509]1397
[562]1398    if (!context->hasServer)
[472]1399    {
[562]1400       CContextClient* client = context->client;
[472]1401
[562]1402       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
[472]1403       if (client->isServerLeader())
1404       {
[562]1405         CMessage msg;
1406         msg << this->getId();
1407         msg << id;
[595]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);
[562]1411         client->sendEvent(event);
[472]1412       }
[562]1413       else client->sendEvent(event);
[472]1414    }
1415   }
[509]1416
[472]1417   void CField::sendAddVariableGroup(const string& id)
1418   {
[562]1419    CContext* context = CContext::getCurrent();
1420    if (!context->hasServer)
[472]1421    {
[562]1422       CContextClient* client = context->client;
[472]1423
[562]1424       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP);
[472]1425       if (client->isServerLeader())
1426       {
[562]1427         CMessage msg;
1428         msg << this->getId();
1429         msg << id;
[595]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);
[562]1433         client->sendEvent(event);
[472]1434       }
[562]1435       else client->sendEvent(event);
[472]1436    }
1437   }
[509]1438
[472]1439   void CField::recvAddVariable(CEventServer& event)
1440   {
[509]1441
[562]1442      CBufferIn* buffer = event.subEvents.begin()->buffer;
[472]1443      string id;
[562]1444      *buffer >> id;
1445      get(id)->recvAddVariable(*buffer);
[472]1446   }
[509]1447
[472]1448   void CField::recvAddVariable(CBufferIn& buffer)
1449   {
[562]1450      string id;
1451      buffer >> id;
1452      addVariable(id);
[472]1453   }
1454
1455   void CField::recvAddVariableGroup(CEventServer& event)
1456   {
[509]1457
[562]1458      CBufferIn* buffer = event.subEvents.begin()->buffer;
[472]1459      string id;
[562]1460      *buffer >> id;
1461      get(id)->recvAddVariableGroup(*buffer);
[472]1462   }
[509]1463
[472]1464   void CField::recvAddVariableGroup(CBufferIn& buffer)
1465   {
[562]1466      string id;
1467      buffer >> id;
1468      addVariableGroup(id);
[472]1469   }
1470
[540]1471   DEFINE_REF_FUNC(Field,field)
[472]1472
[540]1473//  void CField::addReference(CField* field)
1474//  {
[562]1475//    refObject.push_back(field);
[540]1476//  }
1477//
1478//   //----------------------------------------------------------------
1479//
1480//   bool CField::hasDirectFieldReference(void) const
1481//   {
[562]1482//     return !this->field_ref.isEmpty();
[540]1483//   }
1484//
1485//   //----------------------------------------------------------------
1486//
[562]1487//   const StdString& CField::getBaseFieldId(void) const
[540]1488//   {
[562]1489//      return this->getBaseFieldReference()->getId();
[540]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())
[562]1500//         return this->getBaseFieldReference();
[540]1501//
[562]1502//      if (!CField::has(this->field_ref.getValue()))
[540]1503//         ERROR("CField::getDirectFieldReference(void)",
1504//               << "[ ref_name = " << this->field_ref.getValue() << "]"
1505//               << " invalid field name !");
1506//
[562]1507//      return CField::get(this->field_ref.getValue());
[540]1508//   }
1509//
1510//   //----------------------------------------------------------------
1511//
1512//   CField* CField::getBaseFieldReference(void) const
1513//   {
[562]1514//      return baseRefObject;
[540]1515//   }
1516//
1517//   //----------------------------------------------------------------
1518//
1519//   const std::vector<CField*>& CField::getAllReference(void) const
1520//   {
[562]1521//      return refObject;
[540]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;
[562]1536//      CField* refer_ptr = this;
[540]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;
[562]1570//      CField* refer_ptr = this;
[540]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//
[562]1590//      if (hasDirectFieldReference()) baseRefObject->addReference(this);
[540]1591//   }
[335]1592} // namespace xios
Note: See TracBrowser for help on using the repository browser.