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

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

Implementing buffer-size automatic detection in mode connected server-client (client is also server)

+) Rearrange some functions to make sure they work in both cases: connected and seperated
+) Make some cleans of code

Test
+) On Curie
+) Both modes, all tests pass

  • 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: 30.8 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
[509]290   /*!
291   \brief Get pointer to direct field to which the current field refers.
292   */
[347]293   CField* CField::getDirectFieldReference(void) const
[219]294   {
295      if (this->field_ref.isEmpty())
296         return (this->getBaseFieldReference());
297
[346]298      if (! CField::has(this->field_ref.getValue()))
[219]299         ERROR("CField::getDirectFieldReference(void)",
300               << "[ ref_name = " << this->field_ref.getValue() << "]"
301               << " invalid field name !");
302
[346]303      return (CField::get(this->field_ref.getValue()));
[219]304   }
305
306   //----------------------------------------------------------------
307
[347]308   CField* CField::getBaseFieldReference(void) const
[509]309   {
310      return (baseRefObject);
[219]311   }
312
313   //----------------------------------------------------------------
314
[509]315   const std::vector<CField*>& CField::getAllReference(void) const
316   {
[219]317      return (refObject);
318   }
319
320   //----------------------------------------------------------------
321
322   const StdString & CField::getBaseFieldId(void) const
[509]323   {
[219]324      return (this->getBaseFieldReference()->getId());
325   }
[509]326
[219]327   //----------------------------------------------------------------
[509]328
[343]329   const CDuration & CField::getFreqOperation(void) const
[219]330   {
331      return (this->freq_operation);
332   }
[509]333
[219]334   //----------------------------------------------------------------
[343]335   const CDuration & CField::getFreqWrite(void) const
[219]336   {
337      return (this->freq_write);
338   }
[509]339
[219]340   //----------------------------------------------------------------
[509]341
[219]342   boost::shared_ptr<func::CFunctor> CField::getFieldOperation(void) const
343   {
344      return (this->foperation);
345   }
346
347   //----------------------------------------------------------------
348
349   bool CField::hasDirectFieldReference(void) const
[509]350   {
351     return (!this->field_ref.isEmpty());
[219]352   }
[509]353
[310]354   bool CField::isActive(void) const
[509]355   {
356      return (!this->refObject.empty());
[310]357   }
[219]358   //----------------------------------------------------------------
[509]359
[369]360   CArray<double, 1> CField::getData(void) const
[219]361   {
362      return(this->data);
363   }
364
365   //----------------------------------------------------------------
366
[343]367   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
[219]368   {
369      return(this->last_Write);
370   }
371
372   //----------------------------------------------------------------
373
[343]374   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
[219]375   {
376      return(this->last_operation);
377   }
378
379   //----------------------------------------------------------------
380
[509]381//   void CField::processEnabledField(void)
382//   {
383//      if (!processed)
384//      {
385//        processed=true ;
386//        solveRefInheritance(true) ;
387//        solveBaseReference() ;
388//        solveOperation() ;
389//        solveGridReference() ;
390//
391//        if (hasDirectFieldReference()) baseRefObject->processEnabledField() ;
392//        buildExpression();
393//        active=true;
394//      }
395//    }
396
397   void CField::solveAllReferenceEnabledField(bool doSending2Sever)
[459]398   {
[509]399     CContext* context = CContext::getCurrent();
400     if (!areAllReferenceSolved)
401     {
402        areAllReferenceSolved = true;
[510]403        if (context->hasClient)
[509]404        {
405          solveRefInheritance(true);
406          solveBaseReference();
407        }
[478]408
[509]409        solveOperation();
410        solveGridReference();
411     }
412     solveGridDomainAxisRef(doSending2Sever);
413     solveCheckMaskIndex(doSending2Sever);
414   }
415
416   std::map<int, StdSize> CField::getGridDataSize()
417   {
418     return grid->getConnectedServerDataSize();
419   }
420
421   void CField::buildAllExpressionEnabledField()
422   {
423     if (!areAllReferenceSolved) solveAllReferenceEnabledField(true);
424     if (!areAllExpressionBuilt)
425     {
426       areAllExpressionBuilt = true;
427//       solveCheckMaskIndex(true);
428//       solveCheckMaskIndex();
429       if (hasDirectFieldReference()) baseRefObject->buildAllExpressionEnabledField();
430       buildExpression();
431       active=true;
432     }
433   }
434
435   /*!
436   \brief Searching for all reference of a field
437   If a field refers to (an)other field(s), we will search for all its referenced parents.
438   Moreover, if any father, direct or indirect (e.g: two levels up), has non-empty attributes,
439   all its attributes will be added to the current field
440   \param [in] apply Flag to specify whether current field uses attributes of its father
441               in case the attribute is empty (true) or its attributes are replaced by ones of its father (false)
442   */
[445]443   void CField::solveRefInheritance(bool apply)
[219]444   {
445      std::set<CField *> sset;
[347]446      CField* refer_sptr;
[219]447      CField * refer_ptr = this;
[509]448
[478]449      while (refer_ptr->hasDirectFieldReference())
450      {
451         refer_sptr = refer_ptr->getDirectFieldReference();
452         refer_ptr  = refer_sptr;
453
454         if(sset.end() != sset.find(refer_ptr))
455         {
456            DEBUG (<< "Circular dependency stopped for field object on "
457                   << "\"" + refer_ptr->getId() + "\" !");
458            break;
459         }
460
461         SuperClassAttribute::setAttributes(refer_ptr, apply);
462         sset.insert(refer_ptr);
463      }
464   }
465
[509]466
467   /*!
468   \brief Only on SERVER side. Remove all field_ref from current field
469   On creating a new field on server side, redundant "field_ref" is still kept in the attribute list
470   of the current field. This function removes this from current field
471   */
472   void CField::removeRefInheritance()
473   {
474     if (this->field_ref.isEmpty()) return;
475     this->clearAttribute("field_ref");
476   }
477
[478]478   void CField::solveBaseReference(void)
479   {
480      std::set<CField *> sset;
481      CField* refer_sptr;
482      CField * refer_ptr = this;
[509]483
[459]484      if (this->hasDirectFieldReference())  baseRefObject = getDirectFieldReference();
485      else  baseRefObject = CField::get(this);
[509]486
[219]487      while (refer_ptr->hasDirectFieldReference())
488      {
489         refer_sptr = refer_ptr->getDirectFieldReference();
[347]490         refer_ptr  = refer_sptr;
[219]491
492         if(sset.end() != sset.find(refer_ptr))
493         {
[478]494            DEBUG (<< "Circular dependency stopped for field object on "
[219]495                   << "\"" + refer_ptr->getId() + "\" !");
496            break;
497         }
498
499         sset.insert(refer_ptr);
500      }
[509]501
[459]502      if (hasDirectFieldReference()) baseRefObject->addReference(this) ;
[219]503   }
[509]504
[219]505   //----------------------------------------------------------------
506
507   void  CField::solveOperation(void)
508   {
509      using namespace func;
[509]510
[460]511      if (!hasOutputFile && !hasFieldOut) return ;
[509]512
[459]513      StdString id ;
514      if (hasId()) id=getId();
515      else if (!name.isEmpty()) id=name ;
516      else if (hasDirectFieldReference()) id=baseRefObject->getId() ;
[509]517
[347]518      CContext* context = CContext::getCurrent();
[509]519
[436]520      if (freq_op.isEmpty()) freq_op=string("1ts") ;
[509]521
[459]522      if (operation.isEmpty() )
[219]523      {
524         ERROR("CField::solveOperation(void)",
525               << "[ id = " << id << "]"
[421]526               << "Impossible to define an operation for this field !");
[219]527      }
[509]528
[278]529      CDuration freq_offset_ = NoneDu;
530      if (!freq_offset.isEmpty())
531      {
532         freq_offset_ = CDuration::FromString(freq_offset.getValue());
533      }
534      else
535      {
536         freq_offset.setValue(NoneDu.toString());
[509]537      }
[219]538
[300]539//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
540      if (context->hasServer)
[219]541      {
[509]542         if (hasOutputFile)
[460]543         {
544           this->freq_operation_srv =CDuration::FromString(this->file->output_freq.getValue());
545           this->freq_write_srv = CDuration::FromString(this->file->output_freq.getValue());
546         }
[343]547         this->lastlast_Write_srv     = boost::shared_ptr<CDate>
548                        (new CDate(context->getCalendar()->getInitDate()));
549         this->last_Write_srv     = boost::shared_ptr<CDate>
550                        (new CDate(context->getCalendar()->getInitDate()));
551         this->last_operation_srv = boost::shared_ptr<CDate>
552                        (new CDate(context->getCalendar()->getInitDate()));
[300]553//         this->foperation_srv     =
554//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
[509]555
556         if (hasOutputFile)
[460]557         {
[509]558           const CDuration toffset = this->freq_operation_srv - freq_offset_ - context->getCalendar()->getTimeStep();
[460]559           *this->last_operation_srv   = *this->last_operation_srv - toffset;
560         }
[219]561      }
[509]562
[449]563//      if (context->hasClient)
[509]564//      {
[219]565         this->freq_operation = CDuration::FromString(freq_op.getValue());
[460]566         if (hasOutputFile) this->freq_write     = CDuration::FromString(this->file->output_freq.getValue());
[509]567         if (hasFieldOut)
[460]568         {
569           this->freq_write = CDuration::FromString(this->fieldOut->freq_op.getValue());
570         }
[343]571         this->last_Write     = boost::shared_ptr<CDate>
572                        (new CDate(context->getCalendar()->getInitDate()));
573         this->last_operation = boost::shared_ptr<CDate>
574                        (new CDate(context->getCalendar()->getInitDate()));
[509]575
576         const CDuration toffset = this->freq_operation - freq_offset_ - context->getCalendar()->getTimeStep();
577         *this->last_operation   = *this->last_operation - toffset;
578
[436]579        if (operation.get()=="once") isOnceOperation=true ;
580        else isOnceOperation=false;
581        isFirstOperation=true;
[509]582
583
[219]584#define DECLARE_FUNCTOR(MType, mtype)              \
585   if  (operation.getValue().compare(#mtype) == 0) \
586   {                                               \
[470]587      if (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value==true) \
588      { \
589        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data,default_value)); \
[473]590        this->foperation = foperation_; \
[470]591      } \
592      else \
593      { \
594        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
595        this->foperation = foperation_;  \
596      } \
[219]597      return;                                      \
598   }
[509]599
[219]600#include "functor_type.conf"
[509]601
[219]602         ERROR("CField::solveOperation(void)",
603               << "[ operation = " << operation.getValue() << "]"
[421]604               << "The operation is not defined !");
[449]605//      }
[436]606
[509]607
[219]608   }
[509]609
[219]610   //----------------------------------------------------------------
[369]611/*
[219]612   void CField::fromBinary(StdIStream & is)
613   {
614      SuperClass::fromBinary(is);
615#define CLEAR_ATT(name_)\
[369]616      SuperClassAttribute::operator[](#name_)->reset()
[219]617
618         CLEAR_ATT(domain_ref);
619         CLEAR_ATT(axis_ref);
620#undef CLEAR_ATT
621
622   }
[369]623*/
[219]624   //----------------------------------------------------------------
625
626   void CField::solveGridReference(void)
627   {
[347]628      CDomain* domain;
629      CAxis* axis;
[219]630
631      if (!domain_ref.isEmpty())
632      {
[346]633         if (CDomain::has(domain_ref.getValue()))
634            domain = CDomain::get(domain_ref.getValue()) ;
[219]635         else
636            ERROR("CField::solveGridReference(void)",
[421]637                  << "Reference to the domain \'"
638                  << domain_ref.getValue() << "\' is wrong") ;
[219]639      }
640
641      if (!axis_ref.isEmpty())
642      {
[346]643         if (CAxis::has(axis_ref.getValue()))
644            axis = CAxis::get(axis_ref.getValue()) ;
[219]645         else
646            ERROR("CField::solveGridReference(void)",
[421]647                  << "Reference to the axis \'"
648                  << axis_ref.getValue() <<"\' is wrong") ;
[219]649      }
650
651      if (!grid_ref.isEmpty())
652      {
[346]653         if (CGrid::has(grid_ref.getValue()))
654            this->grid = CGrid::get(grid_ref.getValue()) ;
[219]655         else
656            ERROR("CField::solveGridReference(void)",
[421]657                  << "Reference to the grid \'"
658                  << grid_ref.getValue() << "\' is wrong");
[219]659      }
[509]660
[418]661      if (grid_ref.isEmpty() &&  domain_ref.isEmpty())
[219]662      {
663            ERROR("CField::solveGridReference(void)",
[421]664                  << "The horizontal domain for this field is not defined");
[418]665
666     }
[509]667
[418]668     CType<string> goodDomain ;
669     CType<string> goodAxis ;
670     if (!grid_ref.isEmpty())
671     {
672       if (!grid->domain_ref.isEmpty()) goodDomain=grid->domain_ref ;
673       if (!grid->axis_ref.isEmpty()) goodAxis=grid->axis_ref ;
674     }
675     if (!domain_ref.isEmpty()) goodDomain=domain_ref ;
676     if (!axis_ref.isEmpty()) goodAxis=axis_ref ;
[509]677
678
679     if (goodDomain.isEmpty())
[418]680     {
[421]681       ERROR("CField::solveGridReference(void)", << "The horizontal domain for this field is not defined");
[418]682     }
[509]683     else
[418]684     {
685       if (CDomain::has(goodDomain)) domain = CDomain::get(goodDomain) ;
[421]686       else ERROR("CField::solveGridReference(void)",<< "Reference to the domain \'"<<goodDomain.get() << "\' is wrong") ;
[418]687     }
[509]688
[418]689     if (!goodAxis.isEmpty())
690     {
691       if (CAxis::has(goodAxis))  axis = CAxis::get(goodAxis) ;
[421]692       else  ERROR("CField::solveGridReference(void)", << "Reference to the axis \'"
693                  << goodAxis.get() <<"\' is wrong") ;
[509]694     }
695
[418]696     bool nothingToDo=false ;
[509]697
[418]698     if (!grid_ref.isEmpty())
699     {
700       if (!grid->domain_ref.isEmpty() && goodDomain.get() == grid->domain_ref.get())
701         if (goodAxis.isEmpty()) nothingToDo=true ;
[509]702         else if (!grid->axis_ref.isEmpty())
[418]703                 if (grid->axis_ref.get()==goodAxis.get()) nothingToDo=true ;
704     }
[509]705
[418]706     if (!nothingToDo)
707     {
708       if (!goodAxis.isEmpty())
709       {
710         this->grid = CGrid::createGrid(domain, axis) ;
711         this->grid_ref.setValue(this->grid->getId());
712       }
713       else
714       {
715         this->grid = CGrid::createGrid(domain) ;
716         this->grid_ref.setValue(this->grid->getId());
[509]717       }
[418]718     }
719
[509]720//     grid->solveReference() ;
721//     grid->solveDomainAxisRef();
722//     grid->checkMaskIndex();
723   }
[459]724
[509]725   void CField::solveGridDomainAxisRef(bool checkAtt)
726   {
727     grid->solveDomainAxisRef(checkAtt);
[219]728   }
729
[509]730   void CField::solveCheckMaskIndex(bool doSendingIndex)
731   {
732     grid->checkMaskIndex(doSendingIndex);
733   }
[219]734
735   ///-------------------------------------------------------------------
736
737   template <>
738      void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
739   {
740      if (this->group_ref.isEmpty()) return;
741      StdString gref = this->group_ref.getValue();
742
[346]743      if (!CFieldGroup::has(gref))
[219]744         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
745               << "[ gref = " << gref << "]"
746               << " invalid group name !");
747
[347]748      CFieldGroup* group = CFieldGroup::get(gref);
749      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
[219]750
[347]751      std::vector<CField*> allChildren  = group->getAllChildren();
[509]752      std::vector<CField*>::iterator
[219]753         it = allChildren.begin(), end = allChildren.end();
[509]754
[219]755      for (; it != end; it++)
756      {
[347]757         CField* child = *it;
[346]758         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()) ;
[509]759
[219]760      }
761   }
[509]762
[464]763   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
764   {
765     map<int, CArray<double,1>* >::iterator it;
766     for(it=data_srv.begin();it!=data_srv.end();it++) *it->second = (*it->second -addOffset) * 1./scaleFactor  ;
767   }
[509]768
[369]769   void CField::outputField(CArray<double,3>& fieldOut)
[300]770   {
[369]771      map<int, CArray<double,1>* >::iterator it;
[300]772      for(it=data_srv.begin();it!=data_srv.end();it++)
[369]773         grid->outputField(it->first,*it->second, fieldOut) ;
[509]774
[300]775   }
[509]776
[369]777   void CField::outputField(CArray<double,2>& fieldOut)
[300]778   {
[369]779      map<int, CArray<double,1>* >::iterator it;
[219]780
[300]781      for(it=data_srv.begin();it!=data_srv.end();it++)
782      {
[369]783         grid->outputField(it->first,*it->second, fieldOut) ;
[300]784      }
785   }
[219]786   ///-------------------------------------------------------------------
787
[459]788   void CField::parse(xml::CXMLNode & node)
789   {
790      SuperClass::parse(node);
[509]791      if (! node.getContent(this->content))
[472]792      {
[476]793        if (node.goToChildElement())
[472]794        {
[476]795          do
796          {
797            if (node.getElementName()=="variable" || node.getElementName()=="variable_group") this->getVirtualVariableGroup()->parseChild(node);
798          } while (node.goToNextElement()) ;
799          node.goToParentElement();
800        }
[472]801      }
[459]802    }
[509]803
[459]804  CArray<double,1>* CField::getInstantData(void)
805  {
[509]806    if (!hasInstantData)
[459]807    {
808      instantData.resize(grid->storeIndex_client.numElements()) ;
809      hasInstantData=true ;
810    }
811    return &instantData ;
812  }
[509]813
[459]814  void CField::addReference(CField* field)
815  {
816    refObject.push_back(field) ;
817  }
[509]818
[459]819  void CField::addDependency(CField* field, int slotId)
820  {
821    fieldDependency.push_back(pair<CField*,int>(field,slotId)) ;
822  }
[509]823
[459]824  void CField::buildExpression(void)
825  {
[509]826    if (content.size() > 0)
[459]827    {
828      CSimpleNodeExpr* simpleExpr=parseExpr(content+'\0') ;
829      expression=CFieldNode::newNode(simpleExpr) ;
830      delete simpleExpr ;
[460]831      set<string> instantFieldIds ;
832      map<string,CField*> associatedInstantFieldIds ;
833      expression->getInstantFieldIds(instantFieldIds) ;
[509]834      for (set<string>::iterator it=instantFieldIds.begin() ; it!=instantFieldIds.end();++it)
[460]835      {
[509]836        if (*it!="this")
[460]837        {
[509]838          if (CField::has(*it))
[460]839          {
840            CField* field=CField::get(*it) ;
[509]841//            field->processEnabledField() ;
842            field->buildAllExpressionEnabledField();
[460]843            associatedInstantFieldIds[*it]=field ;
844          }
845          else  ERROR("void CField::buildExpression(void)",<<" Field "<<*it<<" does not exist") ;
846        }
847      }
[509]848
[460]849      set<string> averageFieldIds ;
850      map<string,CField*> associatedAverageFieldIds ;
[459]851
[460]852      expression->getAverageFieldIds(averageFieldIds) ;
[509]853      for (set<string>::iterator it=averageFieldIds.begin() ; it!=averageFieldIds.end();++it)
854      {
855        if (CField::has(*it))
[460]856        {
857           CFieldGroup* root=CFieldGroup::get("field_definition") ;
858           CField* averageField=root->createChild() ;
859           CField* instantField=root->createChild() ;
860           averageField->field_ref=*it ;
861           averageField->hasFieldOut=true ;
862           averageField->fieldOut=instantField ;
863           instantField->freq_op=freq_op ;
[509]864//           averageField-> processEnabledField() ;
865           averageField->buildAllExpressionEnabledField();
[460]866           instantField->SuperClassAttribute::setAttributes(averageField, true);
867           instantField->field_ref.reset() ;
868           instantField->operation.reset() ;
869
[509]870//           instantField-> processEnabledField() ;
871           instantField->buildAllExpressionEnabledField();
[460]872           associatedAverageFieldIds[*it]=instantField  ;
873        }
874        else ERROR("void CField::buildExpression(void)",<<" Field "<<*it<<" does not exist") ;
875      }
876
877      expression->reduce(this,associatedInstantFieldIds,associatedAverageFieldIds) ;
878
879      slots.resize(instantFieldIds.size()+averageFieldIds.size()) ;
[459]880      resetSlots() ;
881      int slotId=0 ;
882      set<CField*> fields ;
883      expression->getFields(fields) ;
884      for (set<CField*>::iterator it=fields.begin() ; it!=fields.end();++it,++slotId) (*it)->addDependency(this,slotId) ;
[509]885      hasExpression=true;
[459]886    }
887  }
[509]888
[459]889  void CField::resetSlots(void)
890  {
891    for(vector<bool>::iterator it=slots.begin();it!=slots.end();++it) *it=false ;
892  }
[509]893
[459]894  bool CField::slotsFull(void)
895  {
896    bool ret=true ;
897    for(vector<bool>::iterator it=slots.begin();it!=slots.end();++it) ret &= *it;
898    return ret ;
899  }
900
[509]901
[459]902  void CField::setSlot(int slotId)
903  {
904    CContext* context = CContext::getCurrent() ;
905    const CDate & currDate = context->getCalendar()->getCurrentDate();
[509]906    if (slotUpdateDate==NULL || currDate!=*slotUpdateDate)
[459]907    {
908      resetSlots() ;
909      if (slotUpdateDate==NULL) slotUpdateDate=new CDate(currDate) ;
910      else *slotUpdateDate=currDate ;
911    }
912    slots[slotId]=true ;
913    if (slotsFull())
914    {
915      CArray<double,1> expr(expression->compute()) ;
[509]916
917      if (hasInstantData)
[459]918      {
919        instantData=expr ;
[509]920        for(list< pair<CField *,int> >::iterator it=fieldDependency.begin(); it!=fieldDependency.end(); ++it)
[459]921          if (it->first!=this) it->first->setSlot(it->second) ;
922      }
[509]923
[459]924      if (hasOutputFile) updateDataFromExpression(expr) ;
[509]925
[459]926    }
927  }
[472]928
[509]929   /*!
930     This function retrieves Id of corresponding domain_ref and axis_ref (if any)
931   of a field. In some cases, only domain exists but axis doesn't
932   \return pair of Domain and Axis id
933   */
934   const std::pair<StdString,StdString>& CField::getDomainAxisIds()
935   {
936     CGrid* cgPtr = getRelGrid();
937     if (NULL != cgPtr)
938     {
939       if (NULL != cgPtr->getRelDomain()) domAxisIds_.first = cgPtr->getRelDomain()->getId();
940       if (NULL != cgPtr->getRelAxis()) domAxisIds_.second = cgPtr->getRelAxis()->getId();
941     }
[472]942
[509]943     return (domAxisIds_);
944   }
[472]945
946   CVariable* CField::addVariable(const string& id)
947   {
948     return vVariableGroup->createChild(id) ;
949   }
950
951   CVariableGroup* CField::addVariableGroup(const string& id)
952   {
953     return vVariableGroup->createChildGroup(id) ;
954   }
955
956
[509]957   void CField::sendAddAllVariables()
958   {
959     if (!getAllVariables().empty())
960     {
961       // Firstly, it's necessary to add virtual variable group
962       sendAddVariableGroup(getVirtualVariableGroup()->getId());
963
964       // Okie, now we can add to this variable group
965       std::vector<CVariable*> allVar = getAllVariables();
966       std::vector<CVariable*>::const_iterator it = allVar.begin();
967       std::vector<CVariable*>::const_iterator itE = allVar.end();
968
969       for (; it != itE; ++it)
970       {
971         std::cout << "Variable Fields " << (*it)->getId() << std::endl;
972         this->sendAddVariable((*it)->getId());
973         (*it)->sendAllAttributesToServer();
974         (*it)->sendValue();
975       }
976     }
977   }
978
[472]979   void CField::sendAddVariable(const string& id)
980   {
981    CContext* context=CContext::getCurrent() ;
[509]982
[472]983    if (! context->hasServer )
984    {
985       CContextClient* client=context->client ;
986
[509]987       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE) ;
[472]988       if (client->isServerLeader())
989       {
990         CMessage msg ;
991         msg<<this->getId() ;
992         msg<<id ;
993         event.push(client->getServerLeader(),1,msg) ;
994         client->sendEvent(event) ;
995       }
996       else client->sendEvent(event) ;
997    }
[509]998
[472]999   }
[509]1000
1001
[472]1002   void CField::sendAddVariableGroup(const string& id)
1003   {
1004    CContext* context=CContext::getCurrent() ;
1005    if (! context->hasServer )
1006    {
1007       CContextClient* client=context->client ;
1008
[509]1009       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP) ;
[472]1010       if (client->isServerLeader())
1011       {
1012         CMessage msg ;
1013         msg<<this->getId() ;
1014         msg<<id ;
1015         event.push(client->getServerLeader(),1,msg) ;
1016         client->sendEvent(event) ;
1017       }
1018       else client->sendEvent(event) ;
1019    }
[509]1020
[472]1021   }
[509]1022
[472]1023   void CField::recvAddVariable(CEventServer& event)
1024   {
[509]1025
[472]1026      CBufferIn* buffer=event.subEvents.begin()->buffer;
1027      string id;
1028      *buffer>>id ;
1029      get(id)->recvAddVariable(*buffer) ;
1030   }
[509]1031
1032
[472]1033   void CField::recvAddVariable(CBufferIn& buffer)
1034   {
1035      string id ;
1036      buffer>>id ;
1037      addVariable(id) ;
1038   }
1039
1040   void CField::recvAddVariableGroup(CEventServer& event)
1041   {
[509]1042
[472]1043      CBufferIn* buffer=event.subEvents.begin()->buffer;
1044      string id;
1045      *buffer>>id ;
1046      get(id)->recvAddVariableGroup(*buffer) ;
1047   }
[509]1048
1049
[472]1050   void CField::recvAddVariableGroup(CBufferIn& buffer)
1051   {
1052      string id ;
1053      buffer>>id ;
1054      addVariableGroup(id) ;
1055   }
1056
1057
1058
[509]1059
[335]1060} // namespace xios
Note: See TracBrowser for help on using the repository browser.