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
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.setValue(TimeStep);
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      if (freq_offset.isEmpty())
530        freq_offset.setValue(NoneDu);
531
532//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
533      if (context->hasServer)
534      {
535         if (hasOutputFile)
536         {
537           this->freq_operation_srv = this->file->output_freq.getValue();
538           this->freq_write_srv = this->file->output_freq.getValue();
539         }
540         this->lastlast_Write_srv = boost::shared_ptr<CDate>
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()));
546//         this->foperation_srv     =
547//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
548
549         if (hasOutputFile)
550         {
551           const CDuration toffset = this->freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
552           *this->last_operation_srv   = *this->last_operation_srv - toffset;
553         }
554      }
555
556//      if (context->hasClient)
557//      {
558         this->freq_operation = freq_op.getValue();
559         if (hasOutputFile) this->freq_write = this->file->output_freq.getValue();
560         if (hasFieldOut)
561         {
562           this->freq_write = this->fieldOut->freq_op.getValue();
563         }
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()));
568
569         const CDuration toffset = this->freq_operation - freq_offset.getValue() - context->getCalendar()->getTimeStep();
570         *this->last_operation   = *this->last_operation - toffset;
571
572        if (operation.get()=="once") isOnceOperation=true ;
573        else isOnceOperation=false;
574        isFirstOperation=true;
575
576
577#define DECLARE_FUNCTOR(MType, mtype)              \
578   if  (operation.getValue().compare(#mtype) == 0) \
579   {                                               \
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)); \
583        this->foperation = foperation_; \
584      } \
585      else \
586      { \
587        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
588        this->foperation = foperation_;  \
589      } \
590      return;                                      \
591   }
592
593#include "functor_type.conf"
594
595         ERROR("CField::solveOperation(void)",
596               << "[ operation = " << operation.getValue() << "]"
597               << "The operation is not defined !");
598//      }
599
600
601   }
602
603   //----------------------------------------------------------------
604/*
605   void CField::fromBinary(StdIStream & is)
606   {
607      SuperClass::fromBinary(is);
608#define CLEAR_ATT(name_)\
609      SuperClassAttribute::operator[](#name_)->reset()
610
611         CLEAR_ATT(domain_ref);
612         CLEAR_ATT(axis_ref);
613#undef CLEAR_ATT
614
615   }
616*/
617   //----------------------------------------------------------------
618
619   void CField::solveGridReference(void)
620   {
621      CDomain* domain;
622      CAxis* axis;
623
624      if (!domain_ref.isEmpty())
625      {
626         if (CDomain::has(domain_ref.getValue()))
627            domain = CDomain::get(domain_ref.getValue()) ;
628         else
629            ERROR("CField::solveGridReference(void)",
630                  << "Reference to the domain \'"
631                  << domain_ref.getValue() << "\' is wrong") ;
632      }
633
634      if (!axis_ref.isEmpty())
635      {
636         if (CAxis::has(axis_ref.getValue()))
637            axis = CAxis::get(axis_ref.getValue()) ;
638         else
639            ERROR("CField::solveGridReference(void)",
640                  << "Reference to the axis \'"
641                  << axis_ref.getValue() <<"\' is wrong") ;
642      }
643
644      if (!grid_ref.isEmpty())
645      {
646         if (CGrid::has(grid_ref.getValue()))
647            this->grid = CGrid::get(grid_ref.getValue()) ;
648         else
649            ERROR("CField::solveGridReference(void)",
650                  << "Reference to the grid \'"
651                  << grid_ref.getValue() << "\' is wrong");
652      }
653
654      if (grid_ref.isEmpty() &&  domain_ref.isEmpty())
655      {
656            ERROR("CField::solveGridReference(void)",
657                  << "The horizontal domain for this field is not defined");
658
659     }
660
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 ;
670
671
672     if (goodDomain.isEmpty())
673     {
674       ERROR("CField::solveGridReference(void)", << "The horizontal domain for this field is not defined");
675     }
676     else
677     {
678       if (CDomain::has(goodDomain)) domain = CDomain::get(goodDomain) ;
679       else ERROR("CField::solveGridReference(void)",<< "Reference to the domain \'"<<goodDomain.get() << "\' is wrong") ;
680     }
681
682     if (!goodAxis.isEmpty())
683     {
684       if (CAxis::has(goodAxis))  axis = CAxis::get(goodAxis) ;
685       else  ERROR("CField::solveGridReference(void)", << "Reference to the axis \'"
686                  << goodAxis.get() <<"\' is wrong") ;
687     }
688
689     bool nothingToDo=false ;
690
691     if (!grid_ref.isEmpty())
692     {
693       if (!grid->domain_ref.isEmpty() && goodDomain.get() == grid->domain_ref.get())
694         if (goodAxis.isEmpty()) nothingToDo=true ;
695         else if (!grid->axis_ref.isEmpty())
696                 if (grid->axis_ref.get()==goodAxis.get()) nothingToDo=true ;
697     }
698
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());
710       }
711     }
712
713//     grid->solveReference() ;
714//     grid->solveDomainAxisRef();
715//     grid->checkMaskIndex();
716   }
717
718   void CField::solveGridDomainAxisRef(bool checkAtt)
719   {
720     grid->solveDomainAxisRef(checkAtt);
721   }
722
723   void CField::solveCheckMaskIndex(bool doSendingIndex)
724   {
725     grid->checkMaskIndex(doSendingIndex);
726   }
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
736      if (!CFieldGroup::has(gref))
737         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
738               << "[ gref = " << gref << "]"
739               << " invalid group name !");
740
741      CFieldGroup* group = CFieldGroup::get(gref);
742      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
743
744      std::vector<CField*> allChildren  = group->getAllChildren();
745      std::vector<CField*>::iterator
746         it = allChildren.begin(), end = allChildren.end();
747
748      for (; it != end; it++)
749      {
750         CField* child = *it;
751         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()) ;
752
753      }
754   }
755
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   }
761
762   void CField::outputField(CArray<double,3>& fieldOut)
763   {
764      map<int, CArray<double,1>* >::iterator it;
765      for(it=data_srv.begin();it!=data_srv.end();it++)
766         grid->outputField(it->first,*it->second, fieldOut) ;
767
768   }
769
770   void CField::outputField(CArray<double,2>& fieldOut)
771   {
772      map<int, CArray<double,1>* >::iterator it;
773
774      for(it=data_srv.begin();it!=data_srv.end();it++)
775      {
776         grid->outputField(it->first,*it->second, fieldOut) ;
777      }
778   }
779   ///-------------------------------------------------------------------
780
781   void CField::parse(xml::CXMLNode & node)
782   {
783      SuperClass::parse(node);
784      if (! node.getContent(this->content))
785      {
786        if (node.goToChildElement())
787        {
788          do
789          {
790            if (node.getElementName()=="variable" || node.getElementName()=="variable_group") this->getVirtualVariableGroup()->parseChild(node);
791          } while (node.goToNextElement()) ;
792          node.goToParentElement();
793        }
794      }
795    }
796
797  CArray<double,1>* CField::getInstantData(void)
798  {
799    if (!hasInstantData)
800    {
801      instantData.resize(grid->storeIndex_client.numElements()) ;
802      hasInstantData=true ;
803    }
804    return &instantData ;
805  }
806
807  void CField::addReference(CField* field)
808  {
809    refObject.push_back(field) ;
810  }
811
812  void CField::addDependency(CField* field, int slotId)
813  {
814    fieldDependency.push_back(pair<CField*,int>(field,slotId)) ;
815  }
816
817  void CField::buildExpression(void)
818  {
819    if (content.size() > 0)
820    {
821      CSimpleNodeExpr* simpleExpr=parseExpr(content+'\0') ;
822      expression=CFieldNode::newNode(simpleExpr) ;
823      delete simpleExpr ;
824      set<string> instantFieldIds ;
825      map<string,CField*> associatedInstantFieldIds ;
826      expression->getInstantFieldIds(instantFieldIds) ;
827      for (set<string>::iterator it=instantFieldIds.begin() ; it!=instantFieldIds.end();++it)
828      {
829        if (*it!="this")
830        {
831          if (CField::has(*it))
832          {
833            CField* field=CField::get(*it) ;
834//            field->processEnabledField() ;
835            field->buildAllExpressionEnabledField();
836            associatedInstantFieldIds[*it]=field ;
837          }
838          else  ERROR("void CField::buildExpression(void)",<<" Field "<<*it<<" does not exist") ;
839        }
840      }
841
842      set<string> averageFieldIds ;
843      map<string,CField*> associatedAverageFieldIds ;
844
845      expression->getAverageFieldIds(averageFieldIds) ;
846      for (set<string>::iterator it=averageFieldIds.begin() ; it!=averageFieldIds.end();++it)
847      {
848        if (CField::has(*it))
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 ;
857//           averageField-> processEnabledField() ;
858           averageField->buildAllExpressionEnabledField();
859           instantField->SuperClassAttribute::setAttributes(averageField, true);
860           instantField->field_ref.reset() ;
861           instantField->operation.reset() ;
862
863//           instantField-> processEnabledField() ;
864           instantField->buildAllExpressionEnabledField();
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()) ;
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) ;
878      hasExpression=true;
879    }
880  }
881
882  void CField::resetSlots(void)
883  {
884    for(vector<bool>::iterator it=slots.begin();it!=slots.end();++it) *it=false ;
885  }
886
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
894
895  void CField::setSlot(int slotId)
896  {
897    CContext* context = CContext::getCurrent() ;
898    const CDate & currDate = context->getCalendar()->getCurrentDate();
899    if (slotUpdateDate==NULL || currDate!=*slotUpdateDate)
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()) ;
909
910      if (hasInstantData)
911      {
912        instantData=expr ;
913        for(list< pair<CField *,int> >::iterator it=fieldDependency.begin(); it!=fieldDependency.end(); ++it)
914          if (it->first!=this) it->first->setSlot(it->second) ;
915      }
916
917      if (hasOutputFile) updateDataFromExpression(expr) ;
918
919    }
920  }
921
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     }
935
936     return (domAxisIds_);
937   }
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
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
971   void CField::sendAddVariable(const string& id)
972   {
973    CContext* context=CContext::getCurrent() ;
974
975    if (! context->hasServer )
976    {
977       CContextClient* client=context->client ;
978
979       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE) ;
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    }
990
991   }
992
993
994   void CField::sendAddVariableGroup(const string& id)
995   {
996    CContext* context=CContext::getCurrent() ;
997    if (! context->hasServer )
998    {
999       CContextClient* client=context->client ;
1000
1001       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP) ;
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    }
1012
1013   }
1014
1015   void CField::recvAddVariable(CEventServer& event)
1016   {
1017
1018      CBufferIn* buffer=event.subEvents.begin()->buffer;
1019      string id;
1020      *buffer>>id ;
1021      get(id)->recvAddVariable(*buffer) ;
1022   }
1023
1024
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   {
1034
1035      CBufferIn* buffer=event.subEvents.begin()->buffer;
1036      string id;
1037      *buffer>>id ;
1038      get(id)->recvAddVariableGroup(*buffer) ;
1039   }
1040
1041
1042   void CField::recvAddVariableGroup(CBufferIn& buffer)
1043   {
1044      string id ;
1045      buffer>>id ;
1046      addVariableGroup(id) ;
1047   }
1048
1049
1050
1051
1052} // namespace xios
Note: See TracBrowser for help on using the repository browser.