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

Last change on this file since 510 was 510, checked in by mhnguyen, 9 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
Line 
1#include "field.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6
7#include "node_type.hpp"
8#include "calendar_util.hpp"
9#include "message.hpp"
10#include "xmlioserver_spl.hpp"
11#include "type.hpp"
12#include "context_client.hpp"
13#include <set>
14
15namespace xios{
16
17   /// ////////////////////// Définitions ////////////////////// ///
18
19   CField::CField(void)
20      : CObjectTemplate<CField>(), CFieldAttributes()
21      , refObject(), baseRefObject()
22      , grid(), file()
23      , freq_operation(), freq_write()
24      , nstep(0)
25      , last_Write(), last_operation()
26      , foperation(), hasInstantData(false), hasExpression(false)
27      , active(false) , hasOutputFile(false),hasFieldOut(false), slotUpdateDate(NULL)
28      , processed(false), domAxisIds_("",""), areAllReferenceSolved(false), areAllExpressionBuilt(false)
29      { setVirtualVariableGroup() ; }
30
31   CField::CField(const StdString & id)
32      : CObjectTemplate<CField>(id), CFieldAttributes()
33      , refObject(), baseRefObject()
34      , grid(), file()
35      , freq_operation(), freq_write()
36      , nstep(0)
37      , last_Write(), last_operation()
38      , foperation(), hasInstantData(false), hasExpression(false)
39      , active(false), hasOutputFile(false), hasFieldOut(false), slotUpdateDate(NULL)
40      , processed(false), domAxisIds_("",""), areAllReferenceSolved(false), areAllExpressionBuilt(false)
41   { setVirtualVariableGroup() ; }
42
43   CField::~CField(void)
44   {
45//      this->grid.reset() ;
46//      this->file.reset() ;
47      this->foperation.reset() ;
48      if (hasExpression) delete expression ;
49      if (slotUpdateDate!=NULL) delete slotUpdateDate ;
50
51   }
52
53
54  //----------------------------------------------------------------
55
56   void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
57   {
58      this->vVariableGroup = newVVariableGroup;
59   }
60
61   void CField::setVirtualVariableGroup(void)
62   {
63      this->setVirtualVariableGroup(CVariableGroup::create());
64   }
65
66   CVariableGroup* CField::getVirtualVariableGroup(void) const
67   {
68      return (this->vVariableGroup);
69   }
70
71
72   std::vector<CVariable*> CField::getAllVariables(void) const
73   {
74      return (this->vVariableGroup->getAllChildren());
75   }
76
77   void CField::solveDescInheritance(bool apply, const CAttributeMap * const parent)
78   {
79      SuperClassAttribute::setAttributes(parent,apply);
80      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
81   }
82   //----------------------------------------------------------------
83   //----------------------------------------------------------------
84
85   bool CField::updateDataServer
86      (const CDate & currDate,
87       const std::deque< CArray<double, 1>* > storedClient)
88   {
89      const CDate opeDate      = *last_operation + freq_operation;
90      const CDate writeDate    = *last_Write     + freq_write;
91
92      if (opeDate <= currDate)
93      {
94         if (this->data.numElements() != this->grid->storeIndex[0]->numElements())
95         {
96            this->data.resize(this->grid->storeIndex[0] ->numElements());
97         }
98         CArray<double,1> input(data.numElements()) ;
99         this->grid->inputFieldServer(storedClient, input);
100         (*this->foperation)(input);
101         *last_operation = currDate;
102      }
103      if (writeDate < (currDate + freq_operation))
104      {
105         this->foperation->final();
106         this->incrementNStep();
107         *last_Write = writeDate;
108         return (true);
109      }
110      return (false);
111   }
112
113   bool CField::dispatchEvent(CEventServer& event)
114  {
115
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 ;
125
126            case EVENT_ID_ADD_VARIABLE :
127             recvAddVariable(event) ;
128             return true ;
129             break ;
130
131           case EVENT_ID_ADD_VARIABLE_GROUP :
132             recvAddVariableGroup(event) ;
133             return true ;
134             break ;
135
136        default :
137          ERROR("bool CField::dispatchEvent(CEventServer& event)",<<"Unknown Event") ;
138          return false ;
139      }
140    }
141  }
142
143  void CField::sendUpdateData(void)
144  {
145    CContext* context = CContext::getCurrent() ;
146    CContextClient* client=context->client ;
147
148    CEventClient event(getType(),EVENT_ID_UPDATE_DATA) ;
149
150    map<int,CArray<int, 1>* >::iterator it ;
151    list<shared_ptr<CMessage> > list_msg ;
152    list< CArray<double,1>* > list_data ;
153
154    for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
155    {
156      int rank=(*it).first ;
157      CArray<int,1>& index = *(it->second) ;
158      CArray<double,1> data_tmp(index.numElements()) ;
159
160      for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
161      list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
162      list_data.push_back(new CArray<double,1>(data_tmp)) ;
163      *list_msg.back()<<getId()<<*list_data.back() ;
164      event.push(rank,grid->nbSenders[rank],*list_msg.back()) ;
165    }
166    client->sendEvent(event) ;
167
168    for(list< CArray<double,1>* >::iterator it=list_data.begin();it!=list_data.end();it++) delete *it ;
169  }
170
171  void CField::recvUpdateData(CEventServer& event)
172  {
173    vector<int> ranks ;
174    vector<CBufferIn*> buffers ;
175
176    list<CEventServer::SSubEvent>::iterator it ;
177    string fieldId ;
178
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    }
187    get(fieldId)->recvUpdateData(ranks,buffers) ;
188  }
189
190  void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
191  {
192
193    if (data_srv.empty())
194    {
195      for(map<int, CArray<int, 1>* >::iterator it=grid->out_i_fromClient.begin();it!=grid->out_i_fromClient.end();it++)
196      {
197        int rank=it->first ;
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])))) ;
201      }
202    }
203
204    CContext* context = CContext::getCurrent() ;
205    const CDate & currDate = context->getCalendar()->getCurrentDate();
206    const CDate opeDate      = *last_operation_srv + freq_operation_srv;
207    const CDate writeDate    = *last_Write_srv     + freq_write_srv;
208
209
210
211    if (opeDate <= currDate)
212    {
213      for(int n=0;n<ranks.size();n++)
214      {
215        CArray<double,1> data_tmp ;
216        *buffers[n]>>data_tmp ;
217        (*foperation_srv[ranks[n]])(data_tmp) ;
218      }
219      *last_operation_srv = currDate;
220    }
221
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      }
228
229      *last_Write_srv = writeDate;
230      writeField() ;
231      *lastlast_Write_srv=*last_Write_srv;
232    }
233  }
234
235  void CField::writeField(void)
236  {
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      }
244  }
245   //----------------------------------------------------------------
246
247   void CField::setRelFile(CFile* _file)
248   {
249      this->file = _file;
250      hasOutputFile=true ;
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
261   CGrid* CField::getRelGrid(void) const
262   {
263      return (this->grid);
264   }
265
266   //----------------------------------------------------------------
267
268   CFile* CField::getRelFile(void) const
269   {
270      return (this->file);
271   }
272
273   StdSize CField::getNStep(void) const
274   {
275      return (this->nstep);
276   }
277
278   void CField::incrementNStep(void)
279   {
280      this->nstep++;
281   }
282
283   void CField::resetNStep(void)
284   {
285      this->nstep=0;
286   }
287
288   //----------------------------------------------------------------
289
290   /*!
291   \brief Get pointer to direct field to which the current field refers.
292   */
293   CField* CField::getDirectFieldReference(void) const
294   {
295      if (this->field_ref.isEmpty())
296         return (this->getBaseFieldReference());
297
298      if (! CField::has(this->field_ref.getValue()))
299         ERROR("CField::getDirectFieldReference(void)",
300               << "[ ref_name = " << this->field_ref.getValue() << "]"
301               << " invalid field name !");
302
303      return (CField::get(this->field_ref.getValue()));
304   }
305
306   //----------------------------------------------------------------
307
308   CField* CField::getBaseFieldReference(void) const
309   {
310      return (baseRefObject);
311   }
312
313   //----------------------------------------------------------------
314
315   const std::vector<CField*>& CField::getAllReference(void) const
316   {
317      return (refObject);
318   }
319
320   //----------------------------------------------------------------
321
322   const StdString & CField::getBaseFieldId(void) const
323   {
324      return (this->getBaseFieldReference()->getId());
325   }
326
327   //----------------------------------------------------------------
328
329   const CDuration & CField::getFreqOperation(void) const
330   {
331      return (this->freq_operation);
332   }
333
334   //----------------------------------------------------------------
335   const CDuration & CField::getFreqWrite(void) const
336   {
337      return (this->freq_write);
338   }
339
340   //----------------------------------------------------------------
341
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
350   {
351     return (!this->field_ref.isEmpty());
352   }
353
354   bool CField::isActive(void) const
355   {
356      return (!this->refObject.empty());
357   }
358   //----------------------------------------------------------------
359
360   CArray<double, 1> CField::getData(void) const
361   {
362      return(this->data);
363   }
364
365   //----------------------------------------------------------------
366
367   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
368   {
369      return(this->last_Write);
370   }
371
372   //----------------------------------------------------------------
373
374   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
375   {
376      return(this->last_operation);
377   }
378
379   //----------------------------------------------------------------
380
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)
398   {
399     CContext* context = CContext::getCurrent();
400     if (!areAllReferenceSolved)
401     {
402        areAllReferenceSolved = true;
403        if (context->hasClient)
404        {
405          solveRefInheritance(true);
406          solveBaseReference();
407        }
408
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   */
443   void CField::solveRefInheritance(bool apply)
444   {
445      std::set<CField *> sset;
446      CField* refer_sptr;
447      CField * refer_ptr = this;
448
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
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   void CField::solveBaseReference(void)
479   {
480      std::set<CField *> sset;
481      CField* refer_sptr;
482      CField * refer_ptr = this;
483
484      if (this->hasDirectFieldReference())  baseRefObject = getDirectFieldReference();
485      else  baseRefObject = CField::get(this);
486
487      while (refer_ptr->hasDirectFieldReference())
488      {
489         refer_sptr = refer_ptr->getDirectFieldReference();
490         refer_ptr  = refer_sptr;
491
492         if(sset.end() != sset.find(refer_ptr))
493         {
494            DEBUG (<< "Circular dependency stopped for field object on "
495                   << "\"" + refer_ptr->getId() + "\" !");
496            break;
497         }
498
499         sset.insert(refer_ptr);
500      }
501
502      if (hasDirectFieldReference()) baseRefObject->addReference(this) ;
503   }
504
505   //----------------------------------------------------------------
506
507   void  CField::solveOperation(void)
508   {
509      using namespace func;
510
511      if (!hasOutputFile && !hasFieldOut) return ;
512
513      StdString id ;
514      if (hasId()) id=getId();
515      else if (!name.isEmpty()) id=name ;
516      else if (hasDirectFieldReference()) id=baseRefObject->getId() ;
517
518      CContext* context = CContext::getCurrent();
519
520      if (freq_op.isEmpty()) freq_op=string("1ts") ;
521
522      if (operation.isEmpty() )
523      {
524         ERROR("CField::solveOperation(void)",
525               << "[ id = " << id << "]"
526               << "Impossible to define an operation for this field !");
527      }
528
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());
537      }
538
539//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
540      if (context->hasServer)
541      {
542         if (hasOutputFile)
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         }
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()));
553//         this->foperation_srv     =
554//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
555
556         if (hasOutputFile)
557         {
558           const CDuration toffset = this->freq_operation_srv - freq_offset_ - context->getCalendar()->getTimeStep();
559           *this->last_operation_srv   = *this->last_operation_srv - toffset;
560         }
561      }
562
563//      if (context->hasClient)
564//      {
565         this->freq_operation = CDuration::FromString(freq_op.getValue());
566         if (hasOutputFile) this->freq_write     = CDuration::FromString(this->file->output_freq.getValue());
567         if (hasFieldOut)
568         {
569           this->freq_write = CDuration::FromString(this->fieldOut->freq_op.getValue());
570         }
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()));
575
576         const CDuration toffset = this->freq_operation - freq_offset_ - context->getCalendar()->getTimeStep();
577         *this->last_operation   = *this->last_operation - toffset;
578
579        if (operation.get()=="once") isOnceOperation=true ;
580        else isOnceOperation=false;
581        isFirstOperation=true;
582
583
584#define DECLARE_FUNCTOR(MType, mtype)              \
585   if  (operation.getValue().compare(#mtype) == 0) \
586   {                                               \
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)); \
590        this->foperation = foperation_; \
591      } \
592      else \
593      { \
594        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
595        this->foperation = foperation_;  \
596      } \
597      return;                                      \
598   }
599
600#include "functor_type.conf"
601
602         ERROR("CField::solveOperation(void)",
603               << "[ operation = " << operation.getValue() << "]"
604               << "The operation is not defined !");
605//      }
606
607
608   }
609
610   //----------------------------------------------------------------
611/*
612   void CField::fromBinary(StdIStream & is)
613   {
614      SuperClass::fromBinary(is);
615#define CLEAR_ATT(name_)\
616      SuperClassAttribute::operator[](#name_)->reset()
617
618         CLEAR_ATT(domain_ref);
619         CLEAR_ATT(axis_ref);
620#undef CLEAR_ATT
621
622   }
623*/
624   //----------------------------------------------------------------
625
626   void CField::solveGridReference(void)
627   {
628      CDomain* domain;
629      CAxis* axis;
630
631      if (!domain_ref.isEmpty())
632      {
633         if (CDomain::has(domain_ref.getValue()))
634            domain = CDomain::get(domain_ref.getValue()) ;
635         else
636            ERROR("CField::solveGridReference(void)",
637                  << "Reference to the domain \'"
638                  << domain_ref.getValue() << "\' is wrong") ;
639      }
640
641      if (!axis_ref.isEmpty())
642      {
643         if (CAxis::has(axis_ref.getValue()))
644            axis = CAxis::get(axis_ref.getValue()) ;
645         else
646            ERROR("CField::solveGridReference(void)",
647                  << "Reference to the axis \'"
648                  << axis_ref.getValue() <<"\' is wrong") ;
649      }
650
651      if (!grid_ref.isEmpty())
652      {
653         if (CGrid::has(grid_ref.getValue()))
654            this->grid = CGrid::get(grid_ref.getValue()) ;
655         else
656            ERROR("CField::solveGridReference(void)",
657                  << "Reference to the grid \'"
658                  << grid_ref.getValue() << "\' is wrong");
659      }
660
661      if (grid_ref.isEmpty() &&  domain_ref.isEmpty())
662      {
663            ERROR("CField::solveGridReference(void)",
664                  << "The horizontal domain for this field is not defined");
665
666     }
667
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 ;
677
678
679     if (goodDomain.isEmpty())
680     {
681       ERROR("CField::solveGridReference(void)", << "The horizontal domain for this field is not defined");
682     }
683     else
684     {
685       if (CDomain::has(goodDomain)) domain = CDomain::get(goodDomain) ;
686       else ERROR("CField::solveGridReference(void)",<< "Reference to the domain \'"<<goodDomain.get() << "\' is wrong") ;
687     }
688
689     if (!goodAxis.isEmpty())
690     {
691       if (CAxis::has(goodAxis))  axis = CAxis::get(goodAxis) ;
692       else  ERROR("CField::solveGridReference(void)", << "Reference to the axis \'"
693                  << goodAxis.get() <<"\' is wrong") ;
694     }
695
696     bool nothingToDo=false ;
697
698     if (!grid_ref.isEmpty())
699     {
700       if (!grid->domain_ref.isEmpty() && goodDomain.get() == grid->domain_ref.get())
701         if (goodAxis.isEmpty()) nothingToDo=true ;
702         else if (!grid->axis_ref.isEmpty())
703                 if (grid->axis_ref.get()==goodAxis.get()) nothingToDo=true ;
704     }
705
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());
717       }
718     }
719
720//     grid->solveReference() ;
721//     grid->solveDomainAxisRef();
722//     grid->checkMaskIndex();
723   }
724
725   void CField::solveGridDomainAxisRef(bool checkAtt)
726   {
727     grid->solveDomainAxisRef(checkAtt);
728   }
729
730   void CField::solveCheckMaskIndex(bool doSendingIndex)
731   {
732     grid->checkMaskIndex(doSendingIndex);
733   }
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
743      if (!CFieldGroup::has(gref))
744         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
745               << "[ gref = " << gref << "]"
746               << " invalid group name !");
747
748      CFieldGroup* group = CFieldGroup::get(gref);
749      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
750
751      std::vector<CField*> allChildren  = group->getAllChildren();
752      std::vector<CField*>::iterator
753         it = allChildren.begin(), end = allChildren.end();
754
755      for (; it != end; it++)
756      {
757         CField* child = *it;
758         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()) ;
759
760      }
761   }
762
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   }
768
769   void CField::outputField(CArray<double,3>& fieldOut)
770   {
771      map<int, CArray<double,1>* >::iterator it;
772      for(it=data_srv.begin();it!=data_srv.end();it++)
773         grid->outputField(it->first,*it->second, fieldOut) ;
774
775   }
776
777   void CField::outputField(CArray<double,2>& fieldOut)
778   {
779      map<int, CArray<double,1>* >::iterator it;
780
781      for(it=data_srv.begin();it!=data_srv.end();it++)
782      {
783         grid->outputField(it->first,*it->second, fieldOut) ;
784      }
785   }
786   ///-------------------------------------------------------------------
787
788   void CField::parse(xml::CXMLNode & node)
789   {
790      SuperClass::parse(node);
791      if (! node.getContent(this->content))
792      {
793        if (node.goToChildElement())
794        {
795          do
796          {
797            if (node.getElementName()=="variable" || node.getElementName()=="variable_group") this->getVirtualVariableGroup()->parseChild(node);
798          } while (node.goToNextElement()) ;
799          node.goToParentElement();
800        }
801      }
802    }
803
804  CArray<double,1>* CField::getInstantData(void)
805  {
806    if (!hasInstantData)
807    {
808      instantData.resize(grid->storeIndex_client.numElements()) ;
809      hasInstantData=true ;
810    }
811    return &instantData ;
812  }
813
814  void CField::addReference(CField* field)
815  {
816    refObject.push_back(field) ;
817  }
818
819  void CField::addDependency(CField* field, int slotId)
820  {
821    fieldDependency.push_back(pair<CField*,int>(field,slotId)) ;
822  }
823
824  void CField::buildExpression(void)
825  {
826    if (content.size() > 0)
827    {
828      CSimpleNodeExpr* simpleExpr=parseExpr(content+'\0') ;
829      expression=CFieldNode::newNode(simpleExpr) ;
830      delete simpleExpr ;
831      set<string> instantFieldIds ;
832      map<string,CField*> associatedInstantFieldIds ;
833      expression->getInstantFieldIds(instantFieldIds) ;
834      for (set<string>::iterator it=instantFieldIds.begin() ; it!=instantFieldIds.end();++it)
835      {
836        if (*it!="this")
837        {
838          if (CField::has(*it))
839          {
840            CField* field=CField::get(*it) ;
841//            field->processEnabledField() ;
842            field->buildAllExpressionEnabledField();
843            associatedInstantFieldIds[*it]=field ;
844          }
845          else  ERROR("void CField::buildExpression(void)",<<" Field "<<*it<<" does not exist") ;
846        }
847      }
848
849      set<string> averageFieldIds ;
850      map<string,CField*> associatedAverageFieldIds ;
851
852      expression->getAverageFieldIds(averageFieldIds) ;
853      for (set<string>::iterator it=averageFieldIds.begin() ; it!=averageFieldIds.end();++it)
854      {
855        if (CField::has(*it))
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 ;
864//           averageField-> processEnabledField() ;
865           averageField->buildAllExpressionEnabledField();
866           instantField->SuperClassAttribute::setAttributes(averageField, true);
867           instantField->field_ref.reset() ;
868           instantField->operation.reset() ;
869
870//           instantField-> processEnabledField() ;
871           instantField->buildAllExpressionEnabledField();
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()) ;
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) ;
885      hasExpression=true;
886    }
887  }
888
889  void CField::resetSlots(void)
890  {
891    for(vector<bool>::iterator it=slots.begin();it!=slots.end();++it) *it=false ;
892  }
893
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
901
902  void CField::setSlot(int slotId)
903  {
904    CContext* context = CContext::getCurrent() ;
905    const CDate & currDate = context->getCalendar()->getCurrentDate();
906    if (slotUpdateDate==NULL || currDate!=*slotUpdateDate)
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()) ;
916
917      if (hasInstantData)
918      {
919        instantData=expr ;
920        for(list< pair<CField *,int> >::iterator it=fieldDependency.begin(); it!=fieldDependency.end(); ++it)
921          if (it->first!=this) it->first->setSlot(it->second) ;
922      }
923
924      if (hasOutputFile) updateDataFromExpression(expr) ;
925
926    }
927  }
928
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     }
942
943     return (domAxisIds_);
944   }
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
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
979   void CField::sendAddVariable(const string& id)
980   {
981    CContext* context=CContext::getCurrent() ;
982
983    if (! context->hasServer )
984    {
985       CContextClient* client=context->client ;
986
987       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE) ;
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    }
998
999   }
1000
1001
1002   void CField::sendAddVariableGroup(const string& id)
1003   {
1004    CContext* context=CContext::getCurrent() ;
1005    if (! context->hasServer )
1006    {
1007       CContextClient* client=context->client ;
1008
1009       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP) ;
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    }
1020
1021   }
1022
1023   void CField::recvAddVariable(CEventServer& event)
1024   {
1025
1026      CBufferIn* buffer=event.subEvents.begin()->buffer;
1027      string id;
1028      *buffer>>id ;
1029      get(id)->recvAddVariable(*buffer) ;
1030   }
1031
1032
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   {
1042
1043      CBufferIn* buffer=event.subEvents.begin()->buffer;
1044      string id;
1045      *buffer>>id ;
1046      get(id)->recvAddVariableGroup(*buffer) ;
1047   }
1048
1049
1050   void CField::recvAddVariableGroup(CBufferIn& buffer)
1051   {
1052      string id ;
1053      buffer>>id ;
1054      addVariableGroup(id) ;
1055   }
1056
1057
1058
1059
1060} // namespace xios
Note: See TracBrowser for help on using the repository browser.