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

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

Remove leftovers from the XMLIO age.

  • 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: 31.4 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"
12#include "context_client.hpp"
[586]13#include "context_server.hpp"
[459]14#include <set>
[219]15
[335]16namespace xios{
[509]17
[219]18   /// ////////////////////// Définitions ////////////////////// ///
19
20   CField::CField(void)
21      : CObjectTemplate<CField>(), CFieldAttributes()
22      , refObject(), baseRefObject()
23      , grid(), file()
24      , freq_operation(), freq_write()
[266]25      , nstep(0)
[219]26      , last_Write(), last_operation()
[459]27      , foperation(), hasInstantData(false), hasExpression(false)
[460]28      , active(false) , hasOutputFile(false),hasFieldOut(false), slotUpdateDate(NULL)
[562]29      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false)
30      { setVirtualVariableGroup(); }
[219]31
[562]32   CField::CField(const StdString& id)
[219]33      : CObjectTemplate<CField>(id), CFieldAttributes()
34      , refObject(), baseRefObject()
35      , grid(), file()
36      , freq_operation(), freq_write()
[266]37      , nstep(0)
[219]38      , last_Write(), last_operation()
[466]39      , foperation(), hasInstantData(false), hasExpression(false)
[460]40      , active(false), hasOutputFile(false), hasFieldOut(false), slotUpdateDate(NULL)
[562]41      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false)
42   { setVirtualVariableGroup(); }
[219]43
44   CField::~CField(void)
45   {
[562]46//      this->grid.reset();
47//      this->file.reset();
48      this->foperation.reset();
49      if (hasExpression) delete expression;
50      if (slotUpdateDate != NULL) delete slotUpdateDate;
[509]51
[219]52   }
53
[472]54
55  //----------------------------------------------------------------
56
57   void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
[509]58   {
59      this->vVariableGroup = newVVariableGroup;
[472]60   }
[509]61
[472]62   void CField::setVirtualVariableGroup(void)
63   {
64      this->setVirtualVariableGroup(CVariableGroup::create());
65   }
[509]66
[472]67   CVariableGroup* CField::getVirtualVariableGroup(void) const
68   {
[562]69      return this->vVariableGroup;
[472]70   }
71
[509]72
[472]73   std::vector<CVariable*> CField::getAllVariables(void) const
74   {
[562]75      return this->vVariableGroup->getAllChildren();
[472]76   }
[509]77
[562]78   void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent)
[472]79   {
[562]80      SuperClassAttribute::setAttributes(parent, apply);
[472]81      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
82   }
[219]83   //----------------------------------------------------------------
[472]84   //----------------------------------------------------------------
[219]85
86   bool CField::updateDataServer
[562]87      (const CDate& currDate,
[369]88       const std::deque< CArray<double, 1>* > storedClient)
[219]89   {
[343]90      const CDate opeDate      = *last_operation + freq_operation;
[509]91      const CDate writeDate    = *last_Write     + freq_write;
92
[278]93      if (opeDate <= currDate)
[219]94      {
[369]95         if (this->data.numElements() != this->grid->storeIndex[0]->numElements())
[278]96         {
[562]97            this->data.resize(this->grid->storeIndex[0]->numElements());
[509]98         }
[562]99         CArray<double,1> input(data.numElements());
[509]100         this->grid->inputFieldServer(storedClient, input);
[219]101         (*this->foperation)(input);
102         *last_operation = currDate;
103      }
[278]104      if (writeDate < (currDate + freq_operation))
[219]105      {
[278]106         this->foperation->final();
107         this->incrementNStep();
108         *last_Write = writeDate;
[562]109         return true;
[219]110      }
[562]111      return false;
[219]112   }
[509]113
[300]114   bool CField::dispatchEvent(CEventServer& event)
115  {
[509]116
[562]117    if (SuperClass::dispatchEvent(event)) return true;
[300]118    else
119    {
120      switch(event.type)
121      {
122        case EVENT_ID_UPDATE_DATA :
[562]123          recvUpdateData(event);
124          return true;
125          break;
[472]126
127            case EVENT_ID_ADD_VARIABLE :
[562]128             recvAddVariable(event);
129             return true;
130             break;
[509]131
[472]132           case EVENT_ID_ADD_VARIABLE_GROUP :
[562]133             recvAddVariableGroup(event);
134             return true;
135             break;
[509]136
[300]137        default :
[562]138          ERROR("bool CField::dispatchEvent(CEventServer& event)", << "Unknown Event");
139          return false;
[300]140      }
141    }
142  }
[509]143
[300]144  void CField::sendUpdateData(void)
145  {
[562]146    CContext* context = CContext::getCurrent();
147    CContextClient* client = context->client;
[509]148
[562]149    CEventClient event(getType(),EVENT_ID_UPDATE_DATA);
[509]150
[562]151    map<int,CArray<int, 1>* >::iterator it;
152    list<shared_ptr<CMessage> > list_msg;
153    list< CArray<double,1>* > list_data;
[509]154
[567]155    if (!grid->doGridHaveDataDistributed())
[300]156    {
[569]157       if (0 == client->clientRank)
[567]158       {
159          for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
160          {
161            int rank=(*it).first ;
162            CArray<int,1>& index = *(it->second) ;
163            CArray<double,1> data_tmp(index.numElements()) ;
164            for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
165
166            list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
167            list_data.push_back(new CArray<double,1>(data_tmp)) ;
168            *list_msg.back()<<getId()<<*list_data.back() ;
169            event.push(rank,1,*list_msg.back()) ;
170          }
171          client->sendEvent(event) ;
172       } else client->sendEvent(event);
[300]173    }
[567]174    else
175    {
176      for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
177      {
178        int rank=(*it).first ;
179        CArray<int,1>& index = *(it->second) ;
180        CArray<double,1> data_tmp(index.numElements()) ;
181        for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
182        list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
183        list_data.push_back(new CArray<double,1>(data_tmp)) ;
184        *list_msg.back()<<getId()<<*list_data.back() ;
185        event.push(rank,grid->nbSenders[rank],*list_msg.back()) ;
186      }
187      client->sendEvent(event) ;
188    }
[509]189
[562]190    for (list< CArray<double,1>* >::iterator it = list_data.begin(); it != list_data.end(); it++) delete *it;
[300]191  }
[509]192
[300]193  void CField::recvUpdateData(CEventServer& event)
194  {
[562]195    vector<int> ranks;
196    vector<CBufferIn*> buffers;
[509]197
[562]198    list<CEventServer::SSubEvent>::iterator it;
199    string fieldId;
[219]200
[562]201    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
[300]202    {
[562]203      int rank = it->rank;
204      CBufferIn* buffer = it->buffer;
205      *buffer >> fieldId;
206      ranks.push_back(rank);
207      buffers.push_back(buffer);
[300]208    }
[562]209    get(fieldId)->recvUpdateData(ranks,buffers);
[300]210  }
[509]211
[300]212  void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
213  {
214    if (data_srv.empty())
215    {
[562]216      for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
[300]217      {
[562]218        int rank = it->first;
219        CArray<double,1> data_tmp(it->second->numElements());
220        data_srv.insert( pair<int, CArray<double,1>* >(rank, new CArray<double,1>(data_tmp)));
221        foperation_srv.insert(pair<int,boost::shared_ptr<func::CFunctor> >(rank,boost::shared_ptr<func::CFunctor>(new func::CInstant(*data_srv[rank]))));
[300]222      }
223    }
224
[562]225    CContext* context = CContext::getCurrent();
226    const CDate& currDate = context->getCalendar()->getCurrentDate();
[343]227    const CDate opeDate      = *last_operation_srv + freq_operation_srv;
[509]228    const CDate writeDate    = *last_Write_srv     + freq_write_srv;
[300]229
230    if (opeDate <= currDate)
231    {
[562]232      for (int n = 0; n < ranks.size(); n++)
[300]233      {
[562]234        CArray<double,1> data_tmp;
235        *buffers[n] >> data_tmp;
236        (*foperation_srv[ranks[n]])(data_tmp);
[300]237      }
238      *last_operation_srv = currDate;
239    }
[509]240
[300]241    if (writeDate < (currDate + freq_operation_srv))
242    {
[562]243      for (int n = 0; n < ranks.size(); n++)
[300]244      {
245        this->foperation_srv[ranks[n]]->final();
246      }
[509]247
[300]248      *last_Write_srv = writeDate;
[562]249      writeField();
250      *lastlast_Write_srv = *last_Write_srv;
[300]251    }
252  }
[509]253
[300]254  void CField::writeField(void)
255  {
[562]256    if (!getRelFile()->allDomainEmpty)
[586]257    {
[567]258      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file) //      if (! grid->domain->isEmpty() || getRelFile()->type == CFile::type_attr::one_file)
[379]259      {
260        getRelFile()->checkFile();
261        this->incrementNStep();
262        getRelFile()->getDataOutput()->writeFieldData(CField::get(this));
263      }
[586]264    }
[300]265  }
[562]266
[219]267   //----------------------------------------------------------------
268
[347]269   void CField::setRelFile(CFile* _file)
[509]270   {
[459]271      this->file = _file;
[562]272      hasOutputFile = true;
[219]273   }
274
275   //----------------------------------------------------------------
276
[562]277   StdString CField::GetName(void)    { return StdString("field"); }
278   StdString CField::GetDefName(void) { return CField::GetName(); }
279   ENodeType CField::GetType(void)    { return eField; }
[219]280
281   //----------------------------------------------------------------
282
[347]283   CGrid* CField::getRelGrid(void) const
[509]284   {
[562]285      return this->grid;
[219]286   }
287
288   //----------------------------------------------------------------
289
[347]290   CFile* CField::getRelFile(void) const
[509]291   {
[562]292      return this->file;
[219]293   }
[509]294
[266]295   StdSize CField::getNStep(void) const
296   {
[562]297      return this->nstep;
[266]298   }
[509]299
[266]300   void CField::incrementNStep(void)
301   {
302      this->nstep++;
303   }
[509]304
[321]305   void CField::resetNStep(void)
306   {
[562]307      this->nstep = 0;
[321]308   }
[219]309
310   //----------------------------------------------------------------
311
[562]312   const CDuration& CField::getFreqOperation(void) const
[219]313   {
[562]314      return this->freq_operation;
[219]315   }
[509]316
[219]317   //----------------------------------------------------------------
[562]318
319   const CDuration& CField::getFreqWrite(void) const
[219]320   {
[562]321      return this->freq_write;
[219]322   }
[509]323
[219]324   //----------------------------------------------------------------
[509]325
[219]326   boost::shared_ptr<func::CFunctor> CField::getFieldOperation(void) const
327   {
[562]328      return this->foperation;
[219]329   }
330
[310]331   bool CField::isActive(void) const
[509]332   {
[562]333      return !this->refObject.empty();
[310]334   }
[562]335
[219]336   //----------------------------------------------------------------
[509]337
[369]338   CArray<double, 1> CField::getData(void) const
[219]339   {
340      return(this->data);
341   }
342
343   //----------------------------------------------------------------
344
[343]345   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
[219]346   {
347      return(this->last_Write);
348   }
349
350   //----------------------------------------------------------------
351
[343]352   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
[219]353   {
354      return(this->last_operation);
355   }
356
357   //----------------------------------------------------------------
358
[509]359//   void CField::processEnabledField(void)
360//   {
361//      if (!processed)
362//      {
[562]363//        processed = true;
364//        solveRefInheritance(true);
365//        solveBaseReference();
366//        solveOperation();
367//        solveGridReference();
[509]368//
[562]369//        if (hasDirectFieldReference()) baseRefObject->processEnabledField();
[509]370//        buildExpression();
[562]371//        active = true;
[509]372//      }
373//    }
374
375   void CField::solveAllReferenceEnabledField(bool doSending2Sever)
[459]376   {
[509]377     CContext* context = CContext::getCurrent();
378     if (!areAllReferenceSolved)
379     {
380        areAllReferenceSolved = true;
[510]381        if (context->hasClient)
[509]382        {
383          solveRefInheritance(true);
384          solveBaseReference();
385        }
[478]386
[509]387        solveOperation();
388        solveGridReference();
389     }
390     solveGridDomainAxisRef(doSending2Sever);
391     solveCheckMaskIndex(doSending2Sever);
392   }
393
394   std::map<int, StdSize> CField::getGridDataSize()
395   {
396     return grid->getConnectedServerDataSize();
397   }
398
399   void CField::buildAllExpressionEnabledField()
400   {
401     if (!areAllReferenceSolved) solveAllReferenceEnabledField(true);
402     if (!areAllExpressionBuilt)
403     {
404       areAllExpressionBuilt = true;
405//       solveCheckMaskIndex(true);
406//       solveCheckMaskIndex();
407       if (hasDirectFieldReference()) baseRefObject->buildAllExpressionEnabledField();
408       buildExpression();
[562]409       active = true;
[509]410     }
411   }
412
[219]413   //----------------------------------------------------------------
414
415   void  CField::solveOperation(void)
416   {
417      using namespace func;
[509]418
[562]419      if (!hasOutputFile && !hasFieldOut) return;
[509]420
[562]421      StdString id;
422      if (hasId()) id = getId();
423      else if (!name.isEmpty()) id = name;
424      else if (hasDirectFieldReference()) id = baseRefObject->getId();
[509]425
[347]426      CContext* context = CContext::getCurrent();
[509]427
[538]428      if (freq_op.isEmpty()) freq_op.setValue(TimeStep);
[509]429
[562]430      if (operation.isEmpty())
[219]431      {
432         ERROR("CField::solveOperation(void)",
433               << "[ id = " << id << "]"
[421]434               << "Impossible to define an operation for this field !");
[219]435      }
[509]436
[538]437      if (freq_offset.isEmpty())
438        freq_offset.setValue(NoneDu);
[219]439
[300]440//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
441      if (context->hasServer)
[219]442      {
[509]443         if (hasOutputFile)
[460]444         {
[538]445           this->freq_operation_srv = this->file->output_freq.getValue();
446           this->freq_write_srv = this->file->output_freq.getValue();
[460]447         }
[538]448         this->lastlast_Write_srv = boost::shared_ptr<CDate>
[343]449                        (new CDate(context->getCalendar()->getInitDate()));
450         this->last_Write_srv     = boost::shared_ptr<CDate>
451                        (new CDate(context->getCalendar()->getInitDate()));
452         this->last_operation_srv = boost::shared_ptr<CDate>
453                        (new CDate(context->getCalendar()->getInitDate()));
[300]454//         this->foperation_srv     =
455//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
[509]456
457         if (hasOutputFile)
[460]458         {
[538]459           const CDuration toffset = this->freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
[460]460           *this->last_operation_srv   = *this->last_operation_srv - toffset;
461         }
[219]462      }
[509]463
[449]464//      if (context->hasClient)
[509]465//      {
[538]466         this->freq_operation = freq_op.getValue();
467         if (hasOutputFile) this->freq_write = this->file->output_freq.getValue();
[509]468         if (hasFieldOut)
[460]469         {
[538]470           this->freq_write = this->fieldOut->freq_op.getValue();
[460]471         }
[343]472         this->last_Write     = boost::shared_ptr<CDate>
473                        (new CDate(context->getCalendar()->getInitDate()));
474         this->last_operation = boost::shared_ptr<CDate>
475                        (new CDate(context->getCalendar()->getInitDate()));
[509]476
[538]477         const CDuration toffset = this->freq_operation - freq_offset.getValue() - context->getCalendar()->getTimeStep();
[509]478         *this->last_operation   = *this->last_operation - toffset;
479
[562]480        if (operation.get() == "once") isOnceOperation = true;
481        else isOnceOperation = false;
482        isFirstOperation = true;
[509]483
[562]484#define DECLARE_FUNCTOR(MType, mtype) \
485   if (operation.getValue().compare(#mtype) == 0) \
486   { \
487      if (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true) \
[470]488      { \
489        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data,default_value)); \
[473]490        this->foperation = foperation_; \
[470]491      } \
492      else \
493      { \
494        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
[562]495        this->foperation = foperation_; \
[470]496      } \
[562]497      return; \
[219]498   }
[509]499
[219]500#include "functor_type.conf"
[509]501
[219]502         ERROR("CField::solveOperation(void)",
503               << "[ operation = " << operation.getValue() << "]"
[421]504               << "The operation is not defined !");
[449]505//      }
[219]506   }
[509]507
[219]508   //----------------------------------------------------------------
[369]509/*
[562]510   void CField::fromBinary(StdIStream& is)
[219]511   {
512      SuperClass::fromBinary(is);
513#define CLEAR_ATT(name_)\
[369]514      SuperClassAttribute::operator[](#name_)->reset()
[219]515
516         CLEAR_ATT(domain_ref);
517         CLEAR_ATT(axis_ref);
518#undef CLEAR_ATT
519
520   }
[369]521*/
[219]522   //----------------------------------------------------------------
523
524   void CField::solveGridReference(void)
525   {
[347]526      CDomain* domain;
527      CAxis* axis;
[541]528      std::vector<CDomain*> vecDom;
529      std::vector<CAxis*> vecAxis;
[542]530      std::vector<std::string> domList, axisList;
[219]531
532      if (!domain_ref.isEmpty())
533      {
[346]534         if (CDomain::has(domain_ref.getValue()))
[541]535         {
[562]536           domain = CDomain::get(domain_ref.getValue());
[541]537           vecDom.push_back(domain);
538         }
[219]539         else
540            ERROR("CField::solveGridReference(void)",
[421]541                  << "Reference to the domain \'"
[562]542                  << domain_ref.getValue() << "\' is wrong");
[219]543      }
544
545      if (!axis_ref.isEmpty())
546      {
[346]547         if (CAxis::has(axis_ref.getValue()))
[541]548         {
[562]549           axis = CAxis::get(axis_ref.getValue());
[541]550           vecAxis.push_back(axis);
551         }
[219]552         else
553            ERROR("CField::solveGridReference(void)",
[421]554                  << "Reference to the axis \'"
[562]555                  << axis_ref.getValue() <<"\' is wrong");
[219]556      }
557
558      if (!grid_ref.isEmpty())
559      {
[346]560         if (CGrid::has(grid_ref.getValue()))
[541]561         {
[562]562           this->grid = CGrid::get(grid_ref.getValue());
[541]563           domList = grid->getDomainList();
564           axisList = grid->getAxisList();
[586]565           if (domList.empty() && axisList.empty() && (!(this->grid->scalar_grid.getValue())))
566           {
567             this->grid = CGrid::createGrid(vecDom, vecAxis);
568           }
[541]569         }
[219]570         else
571            ERROR("CField::solveGridReference(void)",
[421]572                  << "Reference to the grid \'"
573                  << grid_ref.getValue() << "\' is wrong");
[219]574      }
[586]575      else
576      {
577         this->grid = CGrid::createGrid(vecDom, vecAxis);
578      }
[509]579
[562]580      if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty())
[219]581      {
582            ERROR("CField::solveGridReference(void)",
[540]583                  << "At least one dimension must be defined for this field.");
584      }
[509]585   }
[459]586
[509]587   void CField::solveGridDomainAxisRef(bool checkAtt)
588   {
589     grid->solveDomainAxisRef(checkAtt);
[219]590   }
591
[509]592   void CField::solveCheckMaskIndex(bool doSendingIndex)
593   {
594     grid->checkMaskIndex(doSendingIndex);
595   }
[219]596
597   ///-------------------------------------------------------------------
598
599   template <>
[562]600   void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
[219]601   {
602      if (this->group_ref.isEmpty()) return;
603      StdString gref = this->group_ref.getValue();
604
[346]605      if (!CFieldGroup::has(gref))
[219]606         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
607               << "[ gref = " << gref << "]"
608               << " invalid group name !");
609
[347]610      CFieldGroup* group = CFieldGroup::get(gref);
611      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
[219]612
[347]613      std::vector<CField*> allChildren  = group->getAllChildren();
[562]614      std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end();
[509]615
[219]616      for (; it != end; it++)
617      {
[347]618         CField* child = *it;
[562]619         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId());
[509]620
[219]621      }
622   }
[509]623
[464]624   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
625   {
626     map<int, CArray<double,1>* >::iterator it;
[562]627     for (it = data_srv.begin(); it != data_srv.end(); it++) *it->second = (*it->second - addOffset) / scaleFactor;
[464]628   }
[509]629
[369]630   void CField::outputField(CArray<double,3>& fieldOut)
[300]631   {
[369]632      map<int, CArray<double,1>* >::iterator it;
[562]633      for (it = data_srv.begin(); it != data_srv.end(); it++)
[551]634      {
[562]635        grid->outputField(it->first,*it->second, fieldOut.dataFirst());
[551]636      }
[300]637   }
[509]638
[369]639   void CField::outputField(CArray<double,2>& fieldOut)
[300]640   {
[369]641      map<int, CArray<double,1>* >::iterator it;
[567]642      for(it=data_srv.begin();it!=data_srv.end();it++)
643      {
644         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
645      }
646   }
[219]647
[567]648   void CField::outputField(CArray<double,1>& fieldOut)
649   {
650      map<int, CArray<double,1>* >::iterator it;
651
[562]652      for (it = data_srv.begin(); it != data_srv.end(); it++)
[300]653      {
[567]654         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
[300]655      }
656   }
[551]657
[219]658   ///-------------------------------------------------------------------
659
[562]660   void CField::parse(xml::CXMLNode& node)
[459]661   {
662      SuperClass::parse(node);
[562]663      if (!node.getContent(this->content))
[472]664      {
[476]665        if (node.goToChildElement())
[472]666        {
[476]667          do
668          {
[562]669            if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node);
670          } while (node.goToNextElement());
[476]671          node.goToParentElement();
672        }
[472]673      }
[459]674    }
[509]675
[459]676  CArray<double,1>* CField::getInstantData(void)
677  {
[509]678    if (!hasInstantData)
[459]679    {
[562]680      instantData.resize(grid->storeIndex_client.numElements());
681      hasInstantData = true;
[459]682    }
[562]683    return &instantData;
[459]684  }
[509]685
[459]686  void CField::addDependency(CField* field, int slotId)
687  {
[562]688    fieldDependency.push_back(pair<CField*,int>(field,slotId));
[459]689  }
[509]690
[459]691  void CField::buildExpression(void)
692  {
[509]693    if (content.size() > 0)
[459]694    {
[562]695      CSimpleNodeExpr* simpleExpr = parseExpr(content+'\0');
696      expression = CFieldNode::newNode(simpleExpr);
697      delete simpleExpr;
698      set<string> instantFieldIds;
699      map<string,CField*> associatedInstantFieldIds;
700      expression->getInstantFieldIds(instantFieldIds);
701      for (set<string>::iterator it = instantFieldIds.begin(); it != instantFieldIds.end(); ++it)
[460]702      {
[562]703        if (*it != "this")
[460]704        {
[509]705          if (CField::has(*it))
[460]706          {
[562]707            CField* field = CField::get(*it);
708//            field->processEnabledField();
[509]709            field->buildAllExpressionEnabledField();
[562]710            associatedInstantFieldIds[*it] = field;
[460]711          }
[562]712          else  ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
[460]713        }
714      }
[509]715
[562]716      set<string> averageFieldIds;
717      map<string,CField*> associatedAverageFieldIds;
[459]718
[562]719      expression->getAverageFieldIds(averageFieldIds);
720      for (set<string>::iterator it = averageFieldIds.begin(); it != averageFieldIds.end(); ++it)
[509]721      {
722        if (CField::has(*it))
[460]723        {
[562]724           CFieldGroup* root = CFieldGroup::get("field_definition");
725           CField* averageField = root->createChild();
726           CField* instantField = root->createChild();
727           averageField->field_ref = *it;
728           averageField->hasFieldOut = true;
729           averageField->fieldOut = instantField;
730           instantField->freq_op = freq_op;
731//           averageField-> processEnabledField();
[509]732           averageField->buildAllExpressionEnabledField();
[460]733           instantField->SuperClassAttribute::setAttributes(averageField, true);
[562]734           instantField->field_ref.reset();
735           instantField->operation.reset();
[460]736
[562]737//           instantField-> processEnabledField();
[509]738           instantField->buildAllExpressionEnabledField();
[562]739           associatedAverageFieldIds[*it] = instantField;
[460]740        }
[562]741        else ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
[460]742      }
743
[562]744      expression->reduce(this,associatedInstantFieldIds,associatedAverageFieldIds);
[460]745
[562]746      slots.resize(instantFieldIds.size() + averageFieldIds.size());
747      resetSlots();
748      int slotId = 0;
749      set<CField*> fields;
750      expression->getFields(fields);
751      for (set<CField*>::iterator it = fields.begin(); it != fields.end(); ++it, ++slotId) (*it)->addDependency(this,slotId);
752      hasExpression = true;
[459]753    }
754  }
[509]755
[459]756  void CField::resetSlots(void)
757  {
[562]758    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) *it = false;
[459]759  }
[509]760
[459]761  bool CField::slotsFull(void)
762  {
[562]763    bool ret = true;
764    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) ret &= *it;
765    return ret;
[459]766  }
767
768  void CField::setSlot(int slotId)
769  {
[562]770    CContext* context = CContext::getCurrent();
771    const CDate& currDate = context->getCalendar()->getCurrentDate();
772    if (slotUpdateDate == NULL || currDate != *slotUpdateDate)
[459]773    {
[562]774      resetSlots();
775      if (slotUpdateDate == NULL) slotUpdateDate = new CDate(currDate);
776      else *slotUpdateDate = currDate;
[459]777    }
[562]778    slots[slotId] = true;
[459]779    if (slotsFull())
780    {
[562]781      CArray<double,1> expr(expression->compute());
[509]782
783      if (hasInstantData)
[459]784      {
[562]785        instantData = expr;
786        for (list< pair<CField *,int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it)
787          if (it->first != this) it->first->setSlot(it->second);
[459]788      }
[509]789
[562]790      if (hasOutputFile) updateDataFromExpression(expr);
[509]791
[562]792      const std::vector<CField*>& refField = getAllReference();
793      for (std::vector<CField*>::const_iterator it = refField.begin(); it != refField.end(); it++)
794      {
795        if (!(*it)->hasExpression)
796          (*it)->setDataFromExpression(expr);
797      }
[459]798    }
799  }
[472]800
[509]801   /*!
802     This function retrieves Id of corresponding domain_ref and axis_ref (if any)
803   of a field. In some cases, only domain exists but axis doesn't
804   \return pair of Domain and Axis id
805   */
[569]806   const std::pair<StdString,StdString>& CField::getRefDomainAxisIds()
807   {
808     CGrid* cgPtr = getRelGrid();
809     if (NULL != cgPtr)
810     {
811       std::vector<StdString>::iterator it;
812       if (!domain_ref.isEmpty())
813       {
814         std::vector<StdString> domainList = cgPtr->getDomainList();
815         it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue());
816         if (domainList.end() != it) domAxisIds_.first = *it;
817       }
[472]818
[569]819       if (!axis_ref.isEmpty())
820       {
821         std::vector<StdString> axisList = cgPtr->getAxisList();
822         it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue());
823         if (axisList.end() != it) domAxisIds_.second = *it;
824       }
825     }
826     return (domAxisIds_);
827   }
828
[472]829   CVariable* CField::addVariable(const string& id)
830   {
[562]831     return vVariableGroup->createChild(id);
[472]832   }
833
834   CVariableGroup* CField::addVariableGroup(const string& id)
835   {
[562]836     return vVariableGroup->createChildGroup(id);
[472]837   }
838
[509]839   void CField::sendAddAllVariables()
840   {
841     if (!getAllVariables().empty())
842     {
843       // Firstly, it's necessary to add virtual variable group
844       sendAddVariableGroup(getVirtualVariableGroup()->getId());
845
846       // Okie, now we can add to this variable group
847       std::vector<CVariable*> allVar = getAllVariables();
848       std::vector<CVariable*>::const_iterator it = allVar.begin();
849       std::vector<CVariable*>::const_iterator itE = allVar.end();
850
851       for (; it != itE; ++it)
852       {
853         this->sendAddVariable((*it)->getId());
854         (*it)->sendAllAttributesToServer();
855         (*it)->sendValue();
856       }
857     }
858   }
859
[472]860   void CField::sendAddVariable(const string& id)
861   {
[562]862    CContext* context = CContext::getCurrent();
[509]863
[562]864    if (!context->hasServer)
[472]865    {
[562]866       CContextClient* client = context->client;
[472]867
[562]868       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
[472]869       if (client->isServerLeader())
870       {
[562]871         CMessage msg;
872         msg << this->getId();
873         msg << id;
874         event.push(client->getServerLeader(),1,msg);
875         client->sendEvent(event);
[472]876       }
[562]877       else client->sendEvent(event);
[472]878    }
879   }
[509]880
[472]881   void CField::sendAddVariableGroup(const string& id)
882   {
[562]883    CContext* context = CContext::getCurrent();
884    if (!context->hasServer)
[472]885    {
[562]886       CContextClient* client = context->client;
[472]887
[562]888       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP);
[472]889       if (client->isServerLeader())
890       {
[562]891         CMessage msg;
892         msg << this->getId();
893         msg << id;
894         event.push(client->getServerLeader(),1,msg);
895         client->sendEvent(event);
[472]896       }
[562]897       else client->sendEvent(event);
[472]898    }
899   }
[509]900
[472]901   void CField::recvAddVariable(CEventServer& event)
902   {
[509]903
[562]904      CBufferIn* buffer = event.subEvents.begin()->buffer;
[472]905      string id;
[562]906      *buffer >> id;
907      get(id)->recvAddVariable(*buffer);
[472]908   }
[509]909
[472]910   void CField::recvAddVariable(CBufferIn& buffer)
911   {
[562]912      string id;
913      buffer >> id;
914      addVariable(id);
[472]915   }
916
917   void CField::recvAddVariableGroup(CEventServer& event)
918   {
[509]919
[562]920      CBufferIn* buffer = event.subEvents.begin()->buffer;
[472]921      string id;
[562]922      *buffer >> id;
923      get(id)->recvAddVariableGroup(*buffer);
[472]924   }
[509]925
[472]926   void CField::recvAddVariableGroup(CBufferIn& buffer)
927   {
[562]928      string id;
929      buffer >> id;
930      addVariableGroup(id);
[472]931   }
932
[540]933   DEFINE_REF_FUNC(Field,field)
[472]934
[540]935//  void CField::addReference(CField* field)
936//  {
[562]937//    refObject.push_back(field);
[540]938//  }
939//
940//   //----------------------------------------------------------------
941//
942//   bool CField::hasDirectFieldReference(void) const
943//   {
[562]944//     return !this->field_ref.isEmpty();
[540]945//   }
946//
947//   //----------------------------------------------------------------
948//
[562]949//   const StdString& CField::getBaseFieldId(void) const
[540]950//   {
[562]951//      return this->getBaseFieldReference()->getId();
[540]952//   }
953//
954//   //----------------------------------------------------------------
955//
956//   /*!
957//   \brief Get pointer to direct field to which the current field refers.
958//   */
959//   CField* CField::getDirectFieldReference(void) const
960//   {
961//      if (this->field_ref.isEmpty())
[562]962//         return this->getBaseFieldReference();
[540]963//
[562]964//      if (!CField::has(this->field_ref.getValue()))
[540]965//         ERROR("CField::getDirectFieldReference(void)",
966//               << "[ ref_name = " << this->field_ref.getValue() << "]"
967//               << " invalid field name !");
968//
[562]969//      return CField::get(this->field_ref.getValue());
[540]970//   }
971//
972//   //----------------------------------------------------------------
973//
974//   CField* CField::getBaseFieldReference(void) const
975//   {
[562]976//      return baseRefObject;
[540]977//   }
978//
979//   //----------------------------------------------------------------
980//
981//   const std::vector<CField*>& CField::getAllReference(void) const
982//   {
[562]983//      return refObject;
[540]984//   }
985//
986//   /*!
987//   \brief Searching for all reference of a field
988//   If a field refers to (an)other field(s), we will search for all its referenced parents.
989//   Moreover, if any father, direct or indirect (e.g: two levels up), has non-empty attributes,
990//   all its attributes will be added to the current field
991//   \param [in] apply Flag to specify whether current field uses attributes of its father
992//               in case the attribute is empty (true) or its attributes are replaced by ones of its father (false)
993//   */
994//   void CField::solveRefInheritance(bool apply)
995//   {
996//      std::set<CField *> sset;
997//      CField* refer_sptr;
[562]998//      CField* refer_ptr = this;
[540]999//
1000//      while (refer_ptr->hasDirectFieldReference())
1001//      {
1002//         refer_sptr = refer_ptr->getDirectFieldReference();
1003//         refer_ptr  = refer_sptr;
1004//
1005//         if(sset.end() != sset.find(refer_ptr))
1006//         {
1007//            DEBUG (<< "Circular dependency stopped for field object on "
1008//                   << "\"" + refer_ptr->getId() + "\" !");
1009//            break;
1010//         }
1011//
1012//         SuperClassAttribute::setAttributes(refer_ptr, apply);
1013//         sset.insert(refer_ptr);
1014//      }
1015//   }
1016//
1017//   /*!
1018//   \brief Only on SERVER side. Remove all field_ref from current field
1019//   On creating a new field on server side, redundant "field_ref" is still kept in the attribute list
1020//   of the current field. This function removes this from current field
1021//   */
1022//   void CField::removeRefInheritance()
1023//   {
1024//     if (this->field_ref.isEmpty()) return;
1025//     this->clearAttribute("field_ref");
1026//   }
1027//
1028//   void CField::solveBaseReference(void)
1029//   {
1030//      std::set<CField *> sset;
1031//      CField* refer_sptr;
[562]1032//      CField* refer_ptr = this;
[540]1033//
1034//      if (this->hasDirectFieldReference())  baseRefObject = getDirectFieldReference();
1035//      else  baseRefObject = CField::get(this);
1036//
1037//      while (refer_ptr->hasDirectFieldReference())
1038//      {
1039//         refer_sptr = refer_ptr->getDirectFieldReference();
1040//         refer_ptr  = refer_sptr;
1041//
1042//         if(sset.end() != sset.find(refer_ptr))
1043//         {
1044//            DEBUG (<< "Circular dependency stopped for field object on "
1045//                   << "\"" + refer_ptr->getId() + "\" !");
1046//            break;
1047//         }
1048//
1049//         sset.insert(refer_ptr);
1050//      }
1051//
[562]1052//      if (hasDirectFieldReference()) baseRefObject->addReference(this);
[540]1053//   }
[335]1054} // namespace xios
Note: See TracBrowser for help on using the repository browser.