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

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

Implement reading fields from NetCDF files.

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