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

Last change on this file since 538 was 538, checked in by rlacroix, 10 years ago

Convert more attributes to use the new duration type:

  • field: freq_op and freq_offset
  • file: output_freq, sync_freq and split_freq.

Remember that you now have to use the "xios_duration" type instead of strings to get/set those attributes through the Fortran interface.

  • 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.5 KB
RevLine 
[219]1#include "field.hpp"
2
[352]3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
[219]6
7#include "node_type.hpp"
8#include "calendar_util.hpp"
[352]9#include "message.hpp"
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
[538]520      if (freq_op.isEmpty()) freq_op.setValue(TimeStep);
[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
[538]529      if (freq_offset.isEmpty())
530        freq_offset.setValue(NoneDu);
[219]531
[300]532//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
533      if (context->hasServer)
[219]534      {
[509]535         if (hasOutputFile)
[460]536         {
[538]537           this->freq_operation_srv = this->file->output_freq.getValue();
538           this->freq_write_srv = this->file->output_freq.getValue();
[460]539         }
[538]540         this->lastlast_Write_srv = boost::shared_ptr<CDate>
[343]541                        (new CDate(context->getCalendar()->getInitDate()));
542         this->last_Write_srv     = boost::shared_ptr<CDate>
543                        (new CDate(context->getCalendar()->getInitDate()));
544         this->last_operation_srv = boost::shared_ptr<CDate>
545                        (new CDate(context->getCalendar()->getInitDate()));
[300]546//         this->foperation_srv     =
547//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
[509]548
549         if (hasOutputFile)
[460]550         {
[538]551           const CDuration toffset = this->freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
[460]552           *this->last_operation_srv   = *this->last_operation_srv - toffset;
553         }
[219]554      }
[509]555
[449]556//      if (context->hasClient)
[509]557//      {
[538]558         this->freq_operation = freq_op.getValue();
559         if (hasOutputFile) this->freq_write = this->file->output_freq.getValue();
[509]560         if (hasFieldOut)
[460]561         {
[538]562           this->freq_write = this->fieldOut->freq_op.getValue();
[460]563         }
[343]564         this->last_Write     = boost::shared_ptr<CDate>
565                        (new CDate(context->getCalendar()->getInitDate()));
566         this->last_operation = boost::shared_ptr<CDate>
567                        (new CDate(context->getCalendar()->getInitDate()));
[509]568
[538]569         const CDuration toffset = this->freq_operation - freq_offset.getValue() - context->getCalendar()->getTimeStep();
[509]570         *this->last_operation   = *this->last_operation - toffset;
571
[436]572        if (operation.get()=="once") isOnceOperation=true ;
573        else isOnceOperation=false;
574        isFirstOperation=true;
[509]575
576
[219]577#define DECLARE_FUNCTOR(MType, mtype)              \
578   if  (operation.getValue().compare(#mtype) == 0) \
579   {                                               \
[470]580      if (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value==true) \
581      { \
582        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data,default_value)); \
[473]583        this->foperation = foperation_; \
[470]584      } \
585      else \
586      { \
587        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
588        this->foperation = foperation_;  \
589      } \
[219]590      return;                                      \
591   }
[509]592
[219]593#include "functor_type.conf"
[509]594
[219]595         ERROR("CField::solveOperation(void)",
596               << "[ operation = " << operation.getValue() << "]"
[421]597               << "The operation is not defined !");
[449]598//      }
[436]599
[509]600
[219]601   }
[509]602
[219]603   //----------------------------------------------------------------
[369]604/*
[219]605   void CField::fromBinary(StdIStream & is)
606   {
607      SuperClass::fromBinary(is);
608#define CLEAR_ATT(name_)\
[369]609      SuperClassAttribute::operator[](#name_)->reset()
[219]610
611         CLEAR_ATT(domain_ref);
612         CLEAR_ATT(axis_ref);
613#undef CLEAR_ATT
614
615   }
[369]616*/
[219]617   //----------------------------------------------------------------
618
619   void CField::solveGridReference(void)
620   {
[347]621      CDomain* domain;
622      CAxis* axis;
[219]623
624      if (!domain_ref.isEmpty())
625      {
[346]626         if (CDomain::has(domain_ref.getValue()))
627            domain = CDomain::get(domain_ref.getValue()) ;
[219]628         else
629            ERROR("CField::solveGridReference(void)",
[421]630                  << "Reference to the domain \'"
631                  << domain_ref.getValue() << "\' is wrong") ;
[219]632      }
633
634      if (!axis_ref.isEmpty())
635      {
[346]636         if (CAxis::has(axis_ref.getValue()))
637            axis = CAxis::get(axis_ref.getValue()) ;
[219]638         else
639            ERROR("CField::solveGridReference(void)",
[421]640                  << "Reference to the axis \'"
641                  << axis_ref.getValue() <<"\' is wrong") ;
[219]642      }
643
644      if (!grid_ref.isEmpty())
645      {
[346]646         if (CGrid::has(grid_ref.getValue()))
647            this->grid = CGrid::get(grid_ref.getValue()) ;
[219]648         else
649            ERROR("CField::solveGridReference(void)",
[421]650                  << "Reference to the grid \'"
651                  << grid_ref.getValue() << "\' is wrong");
[219]652      }
[509]653
[418]654      if (grid_ref.isEmpty() &&  domain_ref.isEmpty())
[219]655      {
656            ERROR("CField::solveGridReference(void)",
[421]657                  << "The horizontal domain for this field is not defined");
[418]658
659     }
[509]660
[418]661     CType<string> goodDomain ;
662     CType<string> goodAxis ;
663     if (!grid_ref.isEmpty())
664     {
665       if (!grid->domain_ref.isEmpty()) goodDomain=grid->domain_ref ;
666       if (!grid->axis_ref.isEmpty()) goodAxis=grid->axis_ref ;
667     }
668     if (!domain_ref.isEmpty()) goodDomain=domain_ref ;
669     if (!axis_ref.isEmpty()) goodAxis=axis_ref ;
[509]670
671
672     if (goodDomain.isEmpty())
[418]673     {
[421]674       ERROR("CField::solveGridReference(void)", << "The horizontal domain for this field is not defined");
[418]675     }
[509]676     else
[418]677     {
678       if (CDomain::has(goodDomain)) domain = CDomain::get(goodDomain) ;
[421]679       else ERROR("CField::solveGridReference(void)",<< "Reference to the domain \'"<<goodDomain.get() << "\' is wrong") ;
[418]680     }
[509]681
[418]682     if (!goodAxis.isEmpty())
683     {
684       if (CAxis::has(goodAxis))  axis = CAxis::get(goodAxis) ;
[421]685       else  ERROR("CField::solveGridReference(void)", << "Reference to the axis \'"
686                  << goodAxis.get() <<"\' is wrong") ;
[509]687     }
688
[418]689     bool nothingToDo=false ;
[509]690
[418]691     if (!grid_ref.isEmpty())
692     {
693       if (!grid->domain_ref.isEmpty() && goodDomain.get() == grid->domain_ref.get())
694         if (goodAxis.isEmpty()) nothingToDo=true ;
[509]695         else if (!grid->axis_ref.isEmpty())
[418]696                 if (grid->axis_ref.get()==goodAxis.get()) nothingToDo=true ;
697     }
[509]698
[418]699     if (!nothingToDo)
700     {
701       if (!goodAxis.isEmpty())
702       {
703         this->grid = CGrid::createGrid(domain, axis) ;
704         this->grid_ref.setValue(this->grid->getId());
705       }
706       else
707       {
708         this->grid = CGrid::createGrid(domain) ;
709         this->grid_ref.setValue(this->grid->getId());
[509]710       }
[418]711     }
712
[509]713//     grid->solveReference() ;
714//     grid->solveDomainAxisRef();
715//     grid->checkMaskIndex();
716   }
[459]717
[509]718   void CField::solveGridDomainAxisRef(bool checkAtt)
719   {
720     grid->solveDomainAxisRef(checkAtt);
[219]721   }
722
[509]723   void CField::solveCheckMaskIndex(bool doSendingIndex)
724   {
725     grid->checkMaskIndex(doSendingIndex);
726   }
[219]727
728   ///-------------------------------------------------------------------
729
730   template <>
731      void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
732   {
733      if (this->group_ref.isEmpty()) return;
734      StdString gref = this->group_ref.getValue();
735
[346]736      if (!CFieldGroup::has(gref))
[219]737         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
738               << "[ gref = " << gref << "]"
739               << " invalid group name !");
740
[347]741      CFieldGroup* group = CFieldGroup::get(gref);
742      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
[219]743
[347]744      std::vector<CField*> allChildren  = group->getAllChildren();
[509]745      std::vector<CField*>::iterator
[219]746         it = allChildren.begin(), end = allChildren.end();
[509]747
[219]748      for (; it != end; it++)
749      {
[347]750         CField* child = *it;
[346]751         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()) ;
[509]752
[219]753      }
754   }
[509]755
[464]756   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
757   {
758     map<int, CArray<double,1>* >::iterator it;
759     for(it=data_srv.begin();it!=data_srv.end();it++) *it->second = (*it->second -addOffset) * 1./scaleFactor  ;
760   }
[509]761
[369]762   void CField::outputField(CArray<double,3>& fieldOut)
[300]763   {
[369]764      map<int, CArray<double,1>* >::iterator it;
[300]765      for(it=data_srv.begin();it!=data_srv.end();it++)
[369]766         grid->outputField(it->first,*it->second, fieldOut) ;
[509]767
[300]768   }
[509]769
[369]770   void CField::outputField(CArray<double,2>& fieldOut)
[300]771   {
[369]772      map<int, CArray<double,1>* >::iterator it;
[219]773
[300]774      for(it=data_srv.begin();it!=data_srv.end();it++)
775      {
[369]776         grid->outputField(it->first,*it->second, fieldOut) ;
[300]777      }
778   }
[219]779   ///-------------------------------------------------------------------
780
[459]781   void CField::parse(xml::CXMLNode & node)
782   {
783      SuperClass::parse(node);
[509]784      if (! node.getContent(this->content))
[472]785      {
[476]786        if (node.goToChildElement())
[472]787        {
[476]788          do
789          {
790            if (node.getElementName()=="variable" || node.getElementName()=="variable_group") this->getVirtualVariableGroup()->parseChild(node);
791          } while (node.goToNextElement()) ;
792          node.goToParentElement();
793        }
[472]794      }
[459]795    }
[509]796
[459]797  CArray<double,1>* CField::getInstantData(void)
798  {
[509]799    if (!hasInstantData)
[459]800    {
801      instantData.resize(grid->storeIndex_client.numElements()) ;
802      hasInstantData=true ;
803    }
804    return &instantData ;
805  }
[509]806
[459]807  void CField::addReference(CField* field)
808  {
809    refObject.push_back(field) ;
810  }
[509]811
[459]812  void CField::addDependency(CField* field, int slotId)
813  {
814    fieldDependency.push_back(pair<CField*,int>(field,slotId)) ;
815  }
[509]816
[459]817  void CField::buildExpression(void)
818  {
[509]819    if (content.size() > 0)
[459]820    {
821      CSimpleNodeExpr* simpleExpr=parseExpr(content+'\0') ;
822      expression=CFieldNode::newNode(simpleExpr) ;
823      delete simpleExpr ;
[460]824      set<string> instantFieldIds ;
825      map<string,CField*> associatedInstantFieldIds ;
826      expression->getInstantFieldIds(instantFieldIds) ;
[509]827      for (set<string>::iterator it=instantFieldIds.begin() ; it!=instantFieldIds.end();++it)
[460]828      {
[509]829        if (*it!="this")
[460]830        {
[509]831          if (CField::has(*it))
[460]832          {
833            CField* field=CField::get(*it) ;
[509]834//            field->processEnabledField() ;
835            field->buildAllExpressionEnabledField();
[460]836            associatedInstantFieldIds[*it]=field ;
837          }
838          else  ERROR("void CField::buildExpression(void)",<<" Field "<<*it<<" does not exist") ;
839        }
840      }
[509]841
[460]842      set<string> averageFieldIds ;
843      map<string,CField*> associatedAverageFieldIds ;
[459]844
[460]845      expression->getAverageFieldIds(averageFieldIds) ;
[509]846      for (set<string>::iterator it=averageFieldIds.begin() ; it!=averageFieldIds.end();++it)
847      {
848        if (CField::has(*it))
[460]849        {
850           CFieldGroup* root=CFieldGroup::get("field_definition") ;
851           CField* averageField=root->createChild() ;
852           CField* instantField=root->createChild() ;
853           averageField->field_ref=*it ;
854           averageField->hasFieldOut=true ;
855           averageField->fieldOut=instantField ;
856           instantField->freq_op=freq_op ;
[509]857//           averageField-> processEnabledField() ;
858           averageField->buildAllExpressionEnabledField();
[460]859           instantField->SuperClassAttribute::setAttributes(averageField, true);
860           instantField->field_ref.reset() ;
861           instantField->operation.reset() ;
862
[509]863//           instantField-> processEnabledField() ;
864           instantField->buildAllExpressionEnabledField();
[460]865           associatedAverageFieldIds[*it]=instantField  ;
866        }
867        else ERROR("void CField::buildExpression(void)",<<" Field "<<*it<<" does not exist") ;
868      }
869
870      expression->reduce(this,associatedInstantFieldIds,associatedAverageFieldIds) ;
871
872      slots.resize(instantFieldIds.size()+averageFieldIds.size()) ;
[459]873      resetSlots() ;
874      int slotId=0 ;
875      set<CField*> fields ;
876      expression->getFields(fields) ;
877      for (set<CField*>::iterator it=fields.begin() ; it!=fields.end();++it,++slotId) (*it)->addDependency(this,slotId) ;
[509]878      hasExpression=true;
[459]879    }
880  }
[509]881
[459]882  void CField::resetSlots(void)
883  {
884    for(vector<bool>::iterator it=slots.begin();it!=slots.end();++it) *it=false ;
885  }
[509]886
[459]887  bool CField::slotsFull(void)
888  {
889    bool ret=true ;
890    for(vector<bool>::iterator it=slots.begin();it!=slots.end();++it) ret &= *it;
891    return ret ;
892  }
893
[509]894
[459]895  void CField::setSlot(int slotId)
896  {
897    CContext* context = CContext::getCurrent() ;
898    const CDate & currDate = context->getCalendar()->getCurrentDate();
[509]899    if (slotUpdateDate==NULL || currDate!=*slotUpdateDate)
[459]900    {
901      resetSlots() ;
902      if (slotUpdateDate==NULL) slotUpdateDate=new CDate(currDate) ;
903      else *slotUpdateDate=currDate ;
904    }
905    slots[slotId]=true ;
906    if (slotsFull())
907    {
908      CArray<double,1> expr(expression->compute()) ;
[509]909
910      if (hasInstantData)
[459]911      {
912        instantData=expr ;
[509]913        for(list< pair<CField *,int> >::iterator it=fieldDependency.begin(); it!=fieldDependency.end(); ++it)
[459]914          if (it->first!=this) it->first->setSlot(it->second) ;
915      }
[509]916
[459]917      if (hasOutputFile) updateDataFromExpression(expr) ;
[509]918
[459]919    }
920  }
[472]921
[509]922   /*!
923     This function retrieves Id of corresponding domain_ref and axis_ref (if any)
924   of a field. In some cases, only domain exists but axis doesn't
925   \return pair of Domain and Axis id
926   */
927   const std::pair<StdString,StdString>& CField::getDomainAxisIds()
928   {
929     CGrid* cgPtr = getRelGrid();
930     if (NULL != cgPtr)
931     {
932       if (NULL != cgPtr->getRelDomain()) domAxisIds_.first = cgPtr->getRelDomain()->getId();
933       if (NULL != cgPtr->getRelAxis()) domAxisIds_.second = cgPtr->getRelAxis()->getId();
934     }
[472]935
[509]936     return (domAxisIds_);
937   }
[472]938
939   CVariable* CField::addVariable(const string& id)
940   {
941     return vVariableGroup->createChild(id) ;
942   }
943
944   CVariableGroup* CField::addVariableGroup(const string& id)
945   {
946     return vVariableGroup->createChildGroup(id) ;
947   }
948
949
[509]950   void CField::sendAddAllVariables()
951   {
952     if (!getAllVariables().empty())
953     {
954       // Firstly, it's necessary to add virtual variable group
955       sendAddVariableGroup(getVirtualVariableGroup()->getId());
956
957       // Okie, now we can add to this variable group
958       std::vector<CVariable*> allVar = getAllVariables();
959       std::vector<CVariable*>::const_iterator it = allVar.begin();
960       std::vector<CVariable*>::const_iterator itE = allVar.end();
961
962       for (; it != itE; ++it)
963       {
964         this->sendAddVariable((*it)->getId());
965         (*it)->sendAllAttributesToServer();
966         (*it)->sendValue();
967       }
968     }
969   }
970
[472]971   void CField::sendAddVariable(const string& id)
972   {
973    CContext* context=CContext::getCurrent() ;
[509]974
[472]975    if (! context->hasServer )
976    {
977       CContextClient* client=context->client ;
978
[509]979       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE) ;
[472]980       if (client->isServerLeader())
981       {
982         CMessage msg ;
983         msg<<this->getId() ;
984         msg<<id ;
985         event.push(client->getServerLeader(),1,msg) ;
986         client->sendEvent(event) ;
987       }
988       else client->sendEvent(event) ;
989    }
[509]990
[472]991   }
[509]992
993
[472]994   void CField::sendAddVariableGroup(const string& id)
995   {
996    CContext* context=CContext::getCurrent() ;
997    if (! context->hasServer )
998    {
999       CContextClient* client=context->client ;
1000
[509]1001       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP) ;
[472]1002       if (client->isServerLeader())
1003       {
1004         CMessage msg ;
1005         msg<<this->getId() ;
1006         msg<<id ;
1007         event.push(client->getServerLeader(),1,msg) ;
1008         client->sendEvent(event) ;
1009       }
1010       else client->sendEvent(event) ;
1011    }
[509]1012
[472]1013   }
[509]1014
[472]1015   void CField::recvAddVariable(CEventServer& event)
1016   {
[509]1017
[472]1018      CBufferIn* buffer=event.subEvents.begin()->buffer;
1019      string id;
1020      *buffer>>id ;
1021      get(id)->recvAddVariable(*buffer) ;
1022   }
[509]1023
1024
[472]1025   void CField::recvAddVariable(CBufferIn& buffer)
1026   {
1027      string id ;
1028      buffer>>id ;
1029      addVariable(id) ;
1030   }
1031
1032   void CField::recvAddVariableGroup(CEventServer& event)
1033   {
[509]1034
[472]1035      CBufferIn* buffer=event.subEvents.begin()->buffer;
1036      string id;
1037      *buffer>>id ;
1038      get(id)->recvAddVariableGroup(*buffer) ;
1039   }
[509]1040
1041
[472]1042   void CField::recvAddVariableGroup(CBufferIn& buffer)
1043   {
1044      string id ;
1045      buffer>>id ;
1046      addVariableGroup(id) ;
1047   }
1048
1049
1050
[509]1051
[335]1052} // namespace xios
Note: See TracBrowser for help on using the repository browser.