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

Last change on this file since 547 was 542, checked in by mhnguyen, 10 years ago

Modifying some codes to compromise with the new type of xios and do some final tests

+) Use new stricter type bool
+) Change set_timestep to set_context_attr

Test
+) On Curie
+) test_client and test_complete passed
+) test with LMDZ passed

TODO: It seems the bug of undefined referenced object has gone but there's a need of more tests

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