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

Last change on this file since 470 was 470, checked in by ymipsl, 10 years ago

Enhancement : using new field attribute "detect_missing_value=true" adn defining a default value, the temporal operator (average, minimum, maximum, accumulate ...) detect missing value in the field and don't take them into account to perform the operation.

YM

File size: 23.8 KB
RevLine 
[219]1#include "field.hpp"
2
[352]3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
[219]6
7#include "node_type.hpp"
8#include "calendar_util.hpp"
[352]9#include "message.hpp"
10#include "xmlioserver_spl.hpp"
11#include "type.hpp"
12#include "context_client.hpp"
[459]13#include <set>
[219]14
[335]15namespace xios{
[219]16   
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)
[459]28      , processed(false)
[369]29      { /* Ne rien faire de plus */ }
[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)
[459]40      , processed(false)
[219]41   { /* Ne rien faire de plus */ }
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 ;
50       
[219]51   }
52
53   //----------------------------------------------------------------
54
55   bool CField::updateDataServer
[343]56      (const CDate & currDate,
[369]57       const std::deque< CArray<double, 1>* > storedClient)
[219]58   {
[343]59      const CDate opeDate      = *last_operation + freq_operation;
60      const CDate writeDate    = *last_Write     + freq_write; 
[278]61     
62      if (opeDate <= currDate)
[219]63      {
[369]64         if (this->data.numElements() != this->grid->storeIndex[0]->numElements())
[278]65         {
[369]66            this->data.resize(this->grid->storeIndex[0] ->numElements());
[278]67         } 
[369]68         CArray<double,1> input(data.numElements()) ;
[278]69         this->grid->inputFieldServer(storedClient, input);         
[219]70         (*this->foperation)(input);
71         *last_operation = currDate;
72      }
[278]73      if (writeDate < (currDate + freq_operation))
[219]74      {
[278]75         this->foperation->final();
76         this->incrementNStep();
77         *last_Write = writeDate;
78         return (true);       
[219]79      }
80      return (false);
81   }
[300]82   
83   bool CField::dispatchEvent(CEventServer& event)
84  {
85     
86    if (SuperClass::dispatchEvent(event)) return true ;
87    else
88    {
89      switch(event.type)
90      {
91        case EVENT_ID_UPDATE_DATA :
92          recvUpdateData(event) ;
93          return true ;
94          break ;
95 
96        default :
97          ERROR("bool CField::dispatchEvent(CEventServer& event)",<<"Unknown Event") ;
98          return false ;
99      }
100    }
101  }
102 
103  void CField::sendUpdateData(void)
104  {
[347]105    CContext* context = CContext::getCurrent() ;
[300]106    CContextClient* client=context->client ;
107   
108    CEventClient event(getType(),EVENT_ID_UPDATE_DATA) ;
109   
[369]110    map<int,CArray<int, 1>* >::iterator it ;
[300]111    list<shared_ptr<CMessage> > list_msg ;
[369]112    list< CArray<double,1>* > list_data ;
[300]113   
114    for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
115    {
116      int rank=(*it).first ;
[369]117      CArray<int,1>& index = *(it->second) ;
118      CArray<double,1> data_tmp(index.numElements()) ;
119     
120      for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
[300]121      list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
[369]122      list_data.push_back(new CArray<double,1>(data_tmp)) ;
123      *list_msg.back()<<getId()<<*list_data.back() ;
[300]124      event.push(rank,grid->nbSenders[rank],*list_msg.back()) ;
125    }
126    client->sendEvent(event) ;
[369]127   
128    for(list< CArray<double,1>* >::iterator it=list_data.begin();it!=list_data.end();it++) delete *it ;
[300]129  }
130 
131  void CField::recvUpdateData(CEventServer& event)
132  {
133    vector<int> ranks ;
134    vector<CBufferIn*> buffers ;
135     
136    list<CEventServer::SSubEvent>::iterator it ;
137    string fieldId ;
[219]138
[300]139    for (it=event.subEvents.begin();it!=event.subEvents.end();++it)
140    {
141      int rank=it->rank;
142      CBufferIn* buffer=it->buffer;
143      *buffer>>fieldId ;
144      ranks.push_back(rank) ;
145      buffers.push_back(buffer) ;
146    }
147    get(fieldId)->recvUpdateData(ranks,buffers) ;   
148  }
149 
150  void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
151  {
152   
153    if (data_srv.empty())
154    {
[369]155      for(map<int, CArray<int, 1>* >::iterator it=grid->out_i_fromClient.begin();it!=grid->out_i_fromClient.end();it++)
[300]156      {
157        int rank=it->first ;
[369]158        CArray<double,1> data_tmp(it->second->numElements()) ;
159        data_srv.insert( pair<int, CArray<double,1>* >(rank, new CArray<double,1>(data_tmp) ) ) ;
160        foperation_srv.insert(pair<int,boost::shared_ptr<func::CFunctor> >(rank,boost::shared_ptr<func::CFunctor>(new func::CInstant(*data_srv[rank])))) ;
[300]161      }
162    }
163
[347]164    CContext* context = CContext::getCurrent() ;
[343]165    const CDate & currDate = context->getCalendar()->getCurrentDate();
166    const CDate opeDate      = *last_operation_srv + freq_operation_srv;
167    const CDate writeDate    = *last_Write_srv     + freq_write_srv; 
[300]168   
169
170   
171    if (opeDate <= currDate)
172    {
173      for(int n=0;n<ranks.size();n++)
174      {
[369]175        CArray<double,1> data_tmp ;
[300]176        *buffers[n]>>data_tmp ;
177        (*foperation_srv[ranks[n]])(data_tmp) ;
178      }
179      *last_operation_srv = currDate;
180    }
181     
182    if (writeDate < (currDate + freq_operation_srv))
183    {
184      for(int n=0;n<ranks.size();n++)
185      {
186        this->foperation_srv[ranks[n]]->final();
187      }
188     
189      *last_Write_srv = writeDate;
190      writeField() ;
[334]191      *lastlast_Write_srv=*last_Write_srv;
[300]192    }
193  }
194 
195  void CField::writeField(void)
196  {
[379]197    if (! getRelFile()->allDomainEmpty )
198      if (! grid->domain->isEmpty() || getRelFile()->type == CFile::type_attr::one_file)
199      {
200        getRelFile()->checkFile();
201        this->incrementNStep();
202        getRelFile()->getDataOutput()->writeFieldData(CField::get(this));
203      }
[300]204  }
[219]205   //----------------------------------------------------------------
206
[347]207   void CField::setRelFile(CFile* _file)
[219]208   { 
[459]209      this->file = _file;
210      hasOutputFile=true ; 
[219]211   }
212
213   //----------------------------------------------------------------
214
215   StdString CField::GetName(void)   { return (StdString("field")); }
216   StdString CField::GetDefName(void){ return (CField::GetName()); }
217   ENodeType CField::GetType(void)   { return (eField); }
218
219   //----------------------------------------------------------------
220
[347]221   CGrid* CField::getRelGrid(void) const
[219]222   { 
223      return (this->grid); 
224   }
225
226   //----------------------------------------------------------------
227
[347]228   CFile* CField::getRelFile(void) const
[219]229   { 
230      return (this->file);
231   }
[266]232   
233   StdSize CField::getNStep(void) const
234   {
235      return (this->nstep);
236   }
237   
238   void CField::incrementNStep(void)
239   {
240      this->nstep++;
241   }
[321]242 
243   void CField::resetNStep(void)
244   {
245      this->nstep=0;
246   }
[219]247
248   //----------------------------------------------------------------
249
[347]250   CField* CField::getDirectFieldReference(void) const
[219]251   {
252      if (this->field_ref.isEmpty())
253         return (this->getBaseFieldReference());
254
[346]255      if (! CField::has(this->field_ref.getValue()))
[219]256         ERROR("CField::getDirectFieldReference(void)",
257               << "[ ref_name = " << this->field_ref.getValue() << "]"
258               << " invalid field name !");
259
[346]260      return (CField::get(this->field_ref.getValue()));
[219]261   }
262
263   //----------------------------------------------------------------
264
[347]265   CField* CField::getBaseFieldReference(void) const
[219]266   { 
267      return (baseRefObject); 
268   }
269
270   //----------------------------------------------------------------
271
[347]272   const std::vector<CField*>& CField::getAllReference(void) const 
[219]273   { 
274      return (refObject);
275   }
276
277   //----------------------------------------------------------------
278
279   const StdString & CField::getBaseFieldId(void) const
280   { 
281      return (this->getBaseFieldReference()->getId());
282   }
283   
284   //----------------------------------------------------------------
285   
[343]286   const CDuration & CField::getFreqOperation(void) const
[219]287   {
288      return (this->freq_operation);
289   }
290   
291   //----------------------------------------------------------------
[343]292   const CDuration & CField::getFreqWrite(void) const
[219]293   {
294      return (this->freq_write);
295   }
296   
297   //----------------------------------------------------------------
298         
299   boost::shared_ptr<func::CFunctor> CField::getFieldOperation(void) const
300   {
301      return (this->foperation);
302   }
303
304   //----------------------------------------------------------------
305
306   bool CField::hasDirectFieldReference(void) const
307   { 
[310]308     return (!this->field_ref.isEmpty()); 
[219]309   }
310   
[310]311   bool CField::isActive(void) const
312   { 
313      return (!this->refObject.empty()); 
314   }
[219]315   //----------------------------------------------------------------
316   
[369]317   CArray<double, 1> CField::getData(void) const
[219]318   {
319      return(this->data);
320   }
321
322   //----------------------------------------------------------------
323
[343]324   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
[219]325   {
326      return(this->last_Write);
327   }
328
329   //----------------------------------------------------------------
330
[343]331   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
[219]332   {
333      return(this->last_operation);
334   }
335
336   //----------------------------------------------------------------
337
[459]338   void CField::processEnabledField(void)
339   {
340      if (!processed)
341      {
342        processed=true ;
343        solveRefInheritance(true) ;
344        solveOperation() ;
345        solveGridReference() ;
346     
347        if (hasDirectFieldReference()) baseRefObject->processEnabledField() ;
348        buildExpression(); 
349        active=true;
350      }
351    }
352   
[445]353   void CField::solveRefInheritance(bool apply)
[219]354   {
355      std::set<CField *> sset;
[347]356      CField* refer_sptr;
[219]357      CField * refer_ptr = this;
358     
[459]359      if (this->hasDirectFieldReference())  baseRefObject = getDirectFieldReference();
360      else  baseRefObject = CField::get(this);
[219]361     
362      while (refer_ptr->hasDirectFieldReference())
363      {
364         refer_sptr = refer_ptr->getDirectFieldReference();
[347]365         refer_ptr  = refer_sptr;
[219]366
367         if(sset.end() != sset.find(refer_ptr))
368         {
369            DEBUG (<< "Dépendance circulaire stoppée pour l'objet de type CField sur "
370                   << "\"" + refer_ptr->getId() + "\" !");
371            break;
372         }
373
[445]374         SuperClassAttribute::setAttributes(refer_ptr, apply);
[219]375         sset.insert(refer_ptr);
[459]376//ym         baseRefObject = refer_sptr;
[286]377//ym         refObject.push_back(refer_sptr);
[219]378      }
[459]379     
380      if (hasDirectFieldReference()) baseRefObject->addReference(this) ;
[219]381   }
382
383   //----------------------------------------------------------------
384
385   void  CField::solveOperation(void)
386   {
387      using namespace func;
[459]388     
[460]389      if (!hasOutputFile && !hasFieldOut) return ;
[459]390     
391      StdString id ;
392      if (hasId()) id=getId();
393      else if (!name.isEmpty()) id=name ;
394      else if (hasDirectFieldReference()) id=baseRefObject->getId() ;
395     
[347]396      CContext* context = CContext::getCurrent();
[436]397     
398      if (freq_op.isEmpty()) freq_op=string("1ts") ;
399     
[459]400      if (operation.isEmpty() )
[219]401      {
402         ERROR("CField::solveOperation(void)",
403               << "[ id = " << id << "]"
[421]404               << "Impossible to define an operation for this field !");
[219]405      }
[278]406     
407      CDuration freq_offset_ = NoneDu;
408      if (!freq_offset.isEmpty())
409      {
410         freq_offset_ = CDuration::FromString(freq_offset.getValue());
411      }
412      else
413      {
414         freq_offset.setValue(NoneDu.toString());
415      } 
[219]416
[300]417//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
418      if (context->hasServer)
[219]419      {
[460]420         if (hasOutputFile) 
421         {
422           this->freq_operation_srv =CDuration::FromString(this->file->output_freq.getValue());
423           this->freq_write_srv = CDuration::FromString(this->file->output_freq.getValue());
424         }
[343]425         this->lastlast_Write_srv     = boost::shared_ptr<CDate>
426                        (new CDate(context->getCalendar()->getInitDate()));
427         this->last_Write_srv     = boost::shared_ptr<CDate>
428                        (new CDate(context->getCalendar()->getInitDate()));
429         this->last_operation_srv = boost::shared_ptr<CDate>
430                        (new CDate(context->getCalendar()->getInitDate()));
[300]431//         this->foperation_srv     =
432//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
[278]433             
[460]434         if (hasOutputFile) 
435         {
436           const CDuration toffset = this->freq_operation_srv - freq_offset_ - context->getCalendar()->getTimeStep(); 
437           *this->last_operation_srv   = *this->last_operation_srv - toffset;
438         }
[219]439      }
[300]440     
[449]441//      if (context->hasClient)
442//      {                 
[219]443         this->freq_operation = CDuration::FromString(freq_op.getValue());
[460]444         if (hasOutputFile) this->freq_write     = CDuration::FromString(this->file->output_freq.getValue());
445         if (hasFieldOut) 
446         {
447           this->freq_write = CDuration::FromString(this->fieldOut->freq_op.getValue());
448         }
[343]449         this->last_Write     = boost::shared_ptr<CDate>
450                        (new CDate(context->getCalendar()->getInitDate()));
451         this->last_operation = boost::shared_ptr<CDate>
452                        (new CDate(context->getCalendar()->getInitDate()));
[278]453                       
[300]454         const CDuration toffset = this->freq_operation - freq_offset_ - context->getCalendar()->getTimeStep(); 
[278]455         *this->last_operation   = *this->last_operation - toffset; 
[436]456     
457        if (operation.get()=="once") isOnceOperation=true ;
458        else isOnceOperation=false;
459        isFirstOperation=true;
[470]460       
461         
[219]462#define DECLARE_FUNCTOR(MType, mtype)              \
463   if  (operation.getValue().compare(#mtype) == 0) \
464   {                                               \
[470]465      if (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value==true) \
466      { \
467        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data,default_value)); \
468        this->foperation = foperation_; \
469      } \
470      else \
471      { \
472        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
473        this->foperation = foperation_;  \
474      } \
[219]475      return;                                      \
476   }
477   
478#include "functor_type.conf"
479         
480         ERROR("CField::solveOperation(void)",
481               << "[ operation = " << operation.getValue() << "]"
[421]482               << "The operation is not defined !");
[449]483//      }
[436]484     
485
[219]486   }
487   
488   //----------------------------------------------------------------
[369]489/*
[219]490   void CField::fromBinary(StdIStream & is)
491   {
492      SuperClass::fromBinary(is);
493#define CLEAR_ATT(name_)\
[369]494      SuperClassAttribute::operator[](#name_)->reset()
[219]495
496         CLEAR_ATT(domain_ref);
497         CLEAR_ATT(axis_ref);
498#undef CLEAR_ATT
499
500   }
[369]501*/
[219]502   //----------------------------------------------------------------
503
504   void CField::solveGridReference(void)
505   {
[347]506      CDomain* domain;
507      CAxis* axis;
[219]508
509      if (!domain_ref.isEmpty())
510      {
[346]511         if (CDomain::has(domain_ref.getValue()))
512            domain = CDomain::get(domain_ref.getValue()) ;
[219]513         else
514            ERROR("CField::solveGridReference(void)",
[421]515                  << "Reference to the domain \'"
516                  << domain_ref.getValue() << "\' is wrong") ;
[219]517      }
518
519      if (!axis_ref.isEmpty())
520      {
[346]521         if (CAxis::has(axis_ref.getValue()))
522            axis = CAxis::get(axis_ref.getValue()) ;
[219]523         else
524            ERROR("CField::solveGridReference(void)",
[421]525                  << "Reference to the axis \'"
526                  << axis_ref.getValue() <<"\' is wrong") ;
[219]527      }
528
529      if (!grid_ref.isEmpty())
530      {
[346]531         if (CGrid::has(grid_ref.getValue()))
532            this->grid = CGrid::get(grid_ref.getValue()) ;
[219]533         else
534            ERROR("CField::solveGridReference(void)",
[421]535                  << "Reference to the grid \'"
536                  << grid_ref.getValue() << "\' is wrong");
[219]537      }
[418]538     
539      if (grid_ref.isEmpty() &&  domain_ref.isEmpty())
[219]540      {
541            ERROR("CField::solveGridReference(void)",
[421]542                  << "The horizontal domain for this field is not defined");
[418]543
544     }
545     
546     CType<string> goodDomain ;
547     CType<string> goodAxis ;
548     if (!grid_ref.isEmpty())
549     {
550       if (!grid->domain_ref.isEmpty()) goodDomain=grid->domain_ref ;
551       if (!grid->axis_ref.isEmpty()) goodAxis=grid->axis_ref ;
552     }
553     if (!domain_ref.isEmpty()) goodDomain=domain_ref ;
554     if (!axis_ref.isEmpty()) goodAxis=axis_ref ;
555     
556     
557     if (goodDomain.isEmpty()) 
558     {
[421]559       ERROR("CField::solveGridReference(void)", << "The horizontal domain for this field is not defined");
[418]560     }
561     else 
562     {
563       if (CDomain::has(goodDomain)) domain = CDomain::get(goodDomain) ;
[421]564       else ERROR("CField::solveGridReference(void)",<< "Reference to the domain \'"<<goodDomain.get() << "\' is wrong") ;
[418]565     }
566 
567     if (!goodAxis.isEmpty())
568     {
569       if (CAxis::has(goodAxis))  axis = CAxis::get(goodAxis) ;
[421]570       else  ERROR("CField::solveGridReference(void)", << "Reference to the axis \'"
571                  << goodAxis.get() <<"\' is wrong") ;
[418]572     } 
573   
574     bool nothingToDo=false ;
575     
576     if (!grid_ref.isEmpty())
577     {
578       if (!grid->domain_ref.isEmpty() && goodDomain.get() == grid->domain_ref.get())
579         if (goodAxis.isEmpty()) nothingToDo=true ;
580         else if (!grid->axis_ref.isEmpty()) 
581                 if (grid->axis_ref.get()==goodAxis.get()) nothingToDo=true ;
582     }
583     
584     if (!nothingToDo)
585     {
586       if (!goodAxis.isEmpty())
587       {
588         this->grid = CGrid::createGrid(domain, axis) ;
589         this->grid_ref.setValue(this->grid->getId());
590       }
591       else
592       {
593         this->grid = CGrid::createGrid(domain) ;
594         this->grid_ref.setValue(this->grid->getId());
595       }   
596     }
597
598     grid->solveReference() ;
[459]599
[219]600   }
601
602
603   ///-------------------------------------------------------------------
604
605   template <>
606      void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
607   {
608      if (this->group_ref.isEmpty()) return;
609      StdString gref = this->group_ref.getValue();
610
[346]611      if (!CFieldGroup::has(gref))
[219]612         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
613               << "[ gref = " << gref << "]"
614               << " invalid group name !");
615
[347]616      CFieldGroup* group = CFieldGroup::get(gref);
617      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
[219]618
[347]619      std::vector<CField*> allChildren  = group->getAllChildren();
620      std::vector<CField*>::iterator
[219]621         it = allChildren.begin(), end = allChildren.end();
622     
623      for (; it != end; it++)
624      {
[347]625         CField* child = *it;
[346]626         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()) ;
627           
[219]628      }
629   }
[300]630   
[464]631   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
632   {
633     map<int, CArray<double,1>* >::iterator it;
634     for(it=data_srv.begin();it!=data_srv.end();it++) *it->second = (*it->second -addOffset) * 1./scaleFactor  ;
635   }
636   
[369]637   void CField::outputField(CArray<double,3>& fieldOut)
[300]638   {
[369]639      map<int, CArray<double,1>* >::iterator it;
[300]640      for(it=data_srv.begin();it!=data_srv.end();it++)
[369]641         grid->outputField(it->first,*it->second, fieldOut) ;
[300]642     
643   }
644   
[369]645   void CField::outputField(CArray<double,2>& fieldOut)
[300]646   {
[369]647      map<int, CArray<double,1>* >::iterator it;
[219]648
[300]649      for(it=data_srv.begin();it!=data_srv.end();it++)
650      {
[369]651         grid->outputField(it->first,*it->second, fieldOut) ;
[300]652      }
653   }
[219]654   ///-------------------------------------------------------------------
655
[459]656   void CField::parse(xml::CXMLNode & node)
657   {
658      SuperClass::parse(node);
659      node.getContent(this->content) ;
660    }
661   
662  CArray<double,1>* CField::getInstantData(void)
663  {
664    if (!hasInstantData) 
665    {
666      instantData.resize(grid->storeIndex_client.numElements()) ;
667      hasInstantData=true ;
668    }
669    return &instantData ;
670  }
671 
672  void CField::addReference(CField* field)
673  {
674    refObject.push_back(field) ;
675  }
676 
677  void CField::addDependency(CField* field, int slotId)
678  {
679    fieldDependency.push_back(pair<CField*,int>(field,slotId)) ;
680  }
681 
682  void CField::buildExpression(void)
683  {
684    if (content.size() > 0) 
685    {
686      CSimpleNodeExpr* simpleExpr=parseExpr(content+'\0') ;
687      expression=CFieldNode::newNode(simpleExpr) ;
688      delete simpleExpr ;
[460]689      set<string> instantFieldIds ;
690      map<string,CField*> associatedInstantFieldIds ;
691      expression->getInstantFieldIds(instantFieldIds) ;
692      for (set<string>::iterator it=instantFieldIds.begin() ; it!=instantFieldIds.end();++it) 
693      {
694        if (*it!="this") 
695        {
696          if (CField::has(*it)) 
697          {
698            CField* field=CField::get(*it) ;
699            field->processEnabledField() ;
700            associatedInstantFieldIds[*it]=field ;
701          }
702          else  ERROR("void CField::buildExpression(void)",<<" Field "<<*it<<" does not exist") ;
703        }
704      }
[459]705     
[460]706      set<string> averageFieldIds ;
707      map<string,CField*> associatedAverageFieldIds ;
[459]708
[460]709      expression->getAverageFieldIds(averageFieldIds) ;
710      for (set<string>::iterator it=averageFieldIds.begin() ; it!=averageFieldIds.end();++it) 
711      {     
712        if (CField::has(*it)) 
713        {
714           CFieldGroup* root=CFieldGroup::get("field_definition") ;
715           CField* averageField=root->createChild() ;
716           CField* instantField=root->createChild() ;
717           averageField->field_ref=*it ;
718           averageField->hasFieldOut=true ;
719           averageField->fieldOut=instantField ;
720           instantField->freq_op=freq_op ;
721           averageField-> processEnabledField() ;
722           cout<<" outputfreq of averageField "<<  freq_op <<"  "<<instantField->freq_op<<"  "<< averageField->freq_write << endl ;
723           instantField->SuperClassAttribute::setAttributes(averageField, true);
724           instantField->field_ref.reset() ;
725           instantField->operation.reset() ;
726
727           instantField-> processEnabledField() ;
728           associatedAverageFieldIds[*it]=instantField  ;
729        }
730        else ERROR("void CField::buildExpression(void)",<<" Field "<<*it<<" does not exist") ;
731      }
732
733      expression->reduce(this,associatedInstantFieldIds,associatedAverageFieldIds) ;
734
735      slots.resize(instantFieldIds.size()+averageFieldIds.size()) ;
[459]736      resetSlots() ;
737      int slotId=0 ;
738      set<CField*> fields ;
739      expression->getFields(fields) ;
740      for (set<CField*>::iterator it=fields.begin() ; it!=fields.end();++it,++slotId) (*it)->addDependency(this,slotId) ;
741      hasExpression=true; 
742    }
743  }
744 
745  void CField::resetSlots(void)
746  {
747    for(vector<bool>::iterator it=slots.begin();it!=slots.end();++it) *it=false ;
748  }
749 
750  bool CField::slotsFull(void)
751  {
752    bool ret=true ;
753    for(vector<bool>::iterator it=slots.begin();it!=slots.end();++it) ret &= *it;
754    return ret ;
755  }
756
757 
758  void CField::setSlot(int slotId)
759  {
760    CContext* context = CContext::getCurrent() ;
761    const CDate & currDate = context->getCalendar()->getCurrentDate();
762    if (slotUpdateDate==NULL || currDate!=*slotUpdateDate) 
763    {
764      resetSlots() ;
765      if (slotUpdateDate==NULL) slotUpdateDate=new CDate(currDate) ;
766      else *slotUpdateDate=currDate ;
767    }
768    slots[slotId]=true ;
769    if (slotsFull())
770    {
771      CArray<double,1> expr(expression->compute()) ;
772     
773      if (hasInstantData) 
774      {
775        instantData=expr ;
776        for(list< pair<CField *,int> >::iterator it=fieldDependency.begin(); it!=fieldDependency.end(); ++it) 
777          if (it->first!=this) it->first->setSlot(it->second) ;
778      }
779     
780      if (hasOutputFile) updateDataFromExpression(expr) ;
781     
782    }
783  }
784 
[335]785} // namespace xios
Note: See TracBrowser for help on using the repository browser.