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

Last change on this file since 436 was 436, checked in by ymipsl, 11 years ago

bug fix :

  • freq_op is now by default of 1 timestep (1ts)
  • once operation is now working as required

YM

File size: 18.0 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"
[219]13
[335]14namespace xios{
[219]15   
16   /// ////////////////////// Définitions ////////////////////// ///
17
18   CField::CField(void)
19      : CObjectTemplate<CField>(), CFieldAttributes()
20      , refObject(), baseRefObject()
21      , grid(), file()
22      , freq_operation(), freq_write()
[266]23      , nstep(0)
[219]24      , last_Write(), last_operation()
25      , foperation()
[369]26      { /* Ne rien faire de plus */ }
[219]27
28   CField::CField(const StdString & id)
29      : CObjectTemplate<CField>(id), CFieldAttributes()
30      , refObject(), baseRefObject()
31      , grid(), file()
32      , freq_operation(), freq_write()
[266]33      , nstep(0)
[219]34      , last_Write(), last_operation()
35      , foperation()
36   { /* Ne rien faire de plus */ }
37
38   CField::~CField(void)
39   {
[347]40//      this->grid.reset() ;
41//      this->file.reset() ;
[219]42      this->foperation.reset() ;
43   }
44
45   //----------------------------------------------------------------
46
47   bool CField::updateDataServer
[343]48      (const CDate & currDate,
[369]49       const std::deque< CArray<double, 1>* > storedClient)
[219]50   {
[343]51      const CDate opeDate      = *last_operation + freq_operation;
52      const CDate writeDate    = *last_Write     + freq_write; 
[278]53     
54      if (opeDate <= currDate)
[219]55      {
[369]56         if (this->data.numElements() != this->grid->storeIndex[0]->numElements())
[278]57         {
[369]58            this->data.resize(this->grid->storeIndex[0] ->numElements());
[278]59         } 
[369]60         CArray<double,1> input(data.numElements()) ;
[278]61         this->grid->inputFieldServer(storedClient, input);         
[219]62         (*this->foperation)(input);
63         *last_operation = currDate;
64      }
[278]65      if (writeDate < (currDate + freq_operation))
[219]66      {
[278]67         this->foperation->final();
68         this->incrementNStep();
69         *last_Write = writeDate;
70         return (true);       
[219]71      }
72      return (false);
73   }
[300]74   
75   bool CField::dispatchEvent(CEventServer& event)
76  {
77     
78    if (SuperClass::dispatchEvent(event)) return true ;
79    else
80    {
81      switch(event.type)
82      {
83        case EVENT_ID_UPDATE_DATA :
84          recvUpdateData(event) ;
85          return true ;
86          break ;
87 
88        default :
89          ERROR("bool CField::dispatchEvent(CEventServer& event)",<<"Unknown Event") ;
90          return false ;
91      }
92    }
93  }
94 
95  void CField::sendUpdateData(void)
96  {
[347]97    CContext* context = CContext::getCurrent() ;
[300]98    CContextClient* client=context->client ;
99   
100    CEventClient event(getType(),EVENT_ID_UPDATE_DATA) ;
101   
[369]102    map<int,CArray<int, 1>* >::iterator it ;
[300]103    list<shared_ptr<CMessage> > list_msg ;
[369]104    list< CArray<double,1>* > list_data ;
[300]105   
106    for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
107    {
108      int rank=(*it).first ;
[369]109      CArray<int,1>& index = *(it->second) ;
110      CArray<double,1> data_tmp(index.numElements()) ;
111     
112      for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
[300]113      list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
[369]114      list_data.push_back(new CArray<double,1>(data_tmp)) ;
115      *list_msg.back()<<getId()<<*list_data.back() ;
[300]116      event.push(rank,grid->nbSenders[rank],*list_msg.back()) ;
117    }
118    client->sendEvent(event) ;
[369]119   
120    for(list< CArray<double,1>* >::iterator it=list_data.begin();it!=list_data.end();it++) delete *it ;
[300]121  }
122 
123  void CField::recvUpdateData(CEventServer& event)
124  {
125    vector<int> ranks ;
126    vector<CBufferIn*> buffers ;
127     
128    list<CEventServer::SSubEvent>::iterator it ;
129    string fieldId ;
[219]130
[300]131    for (it=event.subEvents.begin();it!=event.subEvents.end();++it)
132    {
133      int rank=it->rank;
134      CBufferIn* buffer=it->buffer;
135      *buffer>>fieldId ;
136      ranks.push_back(rank) ;
137      buffers.push_back(buffer) ;
138    }
139    get(fieldId)->recvUpdateData(ranks,buffers) ;   
140  }
141 
142  void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
143  {
144   
145    if (data_srv.empty())
146    {
[369]147      for(map<int, CArray<int, 1>* >::iterator it=grid->out_i_fromClient.begin();it!=grid->out_i_fromClient.end();it++)
[300]148      {
149        int rank=it->first ;
[369]150        CArray<double,1> data_tmp(it->second->numElements()) ;
151        data_srv.insert( pair<int, CArray<double,1>* >(rank, new CArray<double,1>(data_tmp) ) ) ;
152        foperation_srv.insert(pair<int,boost::shared_ptr<func::CFunctor> >(rank,boost::shared_ptr<func::CFunctor>(new func::CInstant(*data_srv[rank])))) ;
[300]153      }
154    }
155
[347]156    CContext* context = CContext::getCurrent() ;
[343]157    const CDate & currDate = context->getCalendar()->getCurrentDate();
158    const CDate opeDate      = *last_operation_srv + freq_operation_srv;
159    const CDate writeDate    = *last_Write_srv     + freq_write_srv; 
[300]160   
161
162   
163    if (opeDate <= currDate)
164    {
165      for(int n=0;n<ranks.size();n++)
166      {
[369]167        CArray<double,1> data_tmp ;
[300]168        *buffers[n]>>data_tmp ;
169        (*foperation_srv[ranks[n]])(data_tmp) ;
170      }
171      *last_operation_srv = currDate;
172    }
173     
174    if (writeDate < (currDate + freq_operation_srv))
175    {
176      for(int n=0;n<ranks.size();n++)
177      {
178        this->foperation_srv[ranks[n]]->final();
179      }
180     
181      *last_Write_srv = writeDate;
182      writeField() ;
[334]183      *lastlast_Write_srv=*last_Write_srv;
[300]184    }
185  }
186 
187  void CField::writeField(void)
188  {
[379]189    if (! getRelFile()->allDomainEmpty )
190      if (! grid->domain->isEmpty() || getRelFile()->type == CFile::type_attr::one_file)
191      {
192        getRelFile()->checkFile();
193        this->incrementNStep();
194        getRelFile()->getDataOutput()->writeFieldData(CField::get(this));
195      }
[300]196  }
[219]197   //----------------------------------------------------------------
198
[347]199   void CField::setRelFile(CFile* _file)
[219]200   { 
201      this->file = _file; 
202   }
203
204   //----------------------------------------------------------------
205
206   StdString CField::GetName(void)   { return (StdString("field")); }
207   StdString CField::GetDefName(void){ return (CField::GetName()); }
208   ENodeType CField::GetType(void)   { return (eField); }
209
210   //----------------------------------------------------------------
211
[347]212   CGrid* CField::getRelGrid(void) const
[219]213   { 
214      return (this->grid); 
215   }
216
217   //----------------------------------------------------------------
218
[347]219   CFile* CField::getRelFile(void) const
[219]220   { 
221      return (this->file);
222   }
[266]223   
224   StdSize CField::getNStep(void) const
225   {
226      return (this->nstep);
227   }
228   
229   void CField::incrementNStep(void)
230   {
231      this->nstep++;
232   }
[321]233 
234   void CField::resetNStep(void)
235   {
236      this->nstep=0;
237   }
[219]238
239   //----------------------------------------------------------------
240
[347]241   CField* CField::getDirectFieldReference(void) const
[219]242   {
243      if (this->field_ref.isEmpty())
244         return (this->getBaseFieldReference());
245
[346]246      if (! CField::has(this->field_ref.getValue()))
[219]247         ERROR("CField::getDirectFieldReference(void)",
248               << "[ ref_name = " << this->field_ref.getValue() << "]"
249               << " invalid field name !");
250
[346]251      return (CField::get(this->field_ref.getValue()));
[219]252   }
253
254   //----------------------------------------------------------------
255
[347]256   CField* CField::getBaseFieldReference(void) const
[219]257   { 
258      return (baseRefObject); 
259   }
260
261   //----------------------------------------------------------------
262
[347]263   const std::vector<CField*>& CField::getAllReference(void) const 
[219]264   { 
265      return (refObject);
266   }
267
268   //----------------------------------------------------------------
269
270   const StdString & CField::getBaseFieldId(void) const
271   { 
272      return (this->getBaseFieldReference()->getId());
273   }
274   
275   //----------------------------------------------------------------
276   
[343]277   const CDuration & CField::getFreqOperation(void) const
[219]278   {
279      return (this->freq_operation);
280   }
281   
282   //----------------------------------------------------------------
[343]283   const CDuration & CField::getFreqWrite(void) const
[219]284   {
285      return (this->freq_write);
286   }
287   
288   //----------------------------------------------------------------
289         
290   boost::shared_ptr<func::CFunctor> CField::getFieldOperation(void) const
291   {
292      return (this->foperation);
293   }
294
295   //----------------------------------------------------------------
296
297   bool CField::hasDirectFieldReference(void) const
298   { 
[310]299     return (!this->field_ref.isEmpty()); 
[219]300   }
301   
[310]302   bool CField::isActive(void) const
303   { 
304      return (!this->refObject.empty()); 
305   }
[219]306   //----------------------------------------------------------------
307   
[369]308   CArray<double, 1> CField::getData(void) const
[219]309   {
310      return(this->data);
311   }
312
313   //----------------------------------------------------------------
314
[343]315   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
[219]316   {
317      return(this->last_Write);
318   }
319
320   //----------------------------------------------------------------
321
[343]322   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
[219]323   {
324      return(this->last_operation);
325   }
326
327   //----------------------------------------------------------------
328
329   void CField::solveRefInheritance(void)
330   {
331      std::set<CField *> sset;
[347]332      CField* refer_sptr;
[219]333      CField * refer_ptr = this;
334     
[346]335      this->baseRefObject = CField::get(this);
[219]336     
337      while (refer_ptr->hasDirectFieldReference())
338      {
339         refer_sptr = refer_ptr->getDirectFieldReference();
[347]340         refer_ptr  = refer_sptr;
[219]341
342         if(sset.end() != sset.find(refer_ptr))
343         {
344            DEBUG (<< "Dépendance circulaire stoppée pour l'objet de type CField sur "
345                   << "\"" + refer_ptr->getId() + "\" !");
346            break;
347         }
348
349         SuperClassAttribute::setAttributes(refer_ptr);
350         sset.insert(refer_ptr);
351         baseRefObject = refer_sptr;
[286]352//ym         refObject.push_back(refer_sptr);
[219]353      }
354   }
355
356   //----------------------------------------------------------------
357
358   void  CField::solveOperation(void)
359   {
360      using namespace func;
361       
362      StdString id = this->getBaseFieldReference()->getId();
[347]363      CContext* context = CContext::getCurrent();
[436]364     
365      if (freq_op.isEmpty()) freq_op=string("1ts") ;
366     
367      if (operation.isEmpty()  || this->file->output_freq.isEmpty())
[219]368      {
369         ERROR("CField::solveOperation(void)",
370               << "[ id = " << id << "]"
[421]371               << "Impossible to define an operation for this field !");
[219]372      }
[278]373     
374      CDuration freq_offset_ = NoneDu;
375      if (!freq_offset.isEmpty())
376      {
377         freq_offset_ = CDuration::FromString(freq_offset.getValue());
378      }
379      else
380      {
381         freq_offset.setValue(NoneDu.toString());
382      } 
[219]383
[300]384//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
385      if (context->hasServer)
[219]386      {
[300]387         this->freq_operation_srv =
[219]388             CDuration::FromString(this->file->output_freq.getValue());
[300]389         this->freq_write_srv     =
[219]390             CDuration::FromString(this->file->output_freq.getValue());
[343]391         this->lastlast_Write_srv     = boost::shared_ptr<CDate>
392                        (new CDate(context->getCalendar()->getInitDate()));
393         this->last_Write_srv     = boost::shared_ptr<CDate>
394                        (new CDate(context->getCalendar()->getInitDate()));
395         this->last_operation_srv = boost::shared_ptr<CDate>
396                        (new CDate(context->getCalendar()->getInitDate()));
[300]397//         this->foperation_srv     =
398//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
[278]399             
[300]400         const CDuration toffset = this->freq_operation_srv - freq_offset_ - context->getCalendar()->getTimeStep(); 
401         *this->last_operation_srv   = *this->last_operation_srv - toffset; 
[219]402      }
[300]403     
404      if (context->hasClient)
[278]405      {                 
[219]406         this->freq_operation = CDuration::FromString(freq_op.getValue());
407         this->freq_write     = CDuration::FromString(this->file->output_freq.getValue());
[343]408         this->last_Write     = boost::shared_ptr<CDate>
409                        (new CDate(context->getCalendar()->getInitDate()));
410         this->last_operation = boost::shared_ptr<CDate>
411                        (new CDate(context->getCalendar()->getInitDate()));
[278]412                       
[300]413         const CDuration toffset = this->freq_operation - freq_offset_ - context->getCalendar()->getTimeStep(); 
[278]414         *this->last_operation   = *this->last_operation - toffset; 
[436]415     
416        if (operation.get()=="once") isOnceOperation=true ;
417        else isOnceOperation=false;
418        isFirstOperation=true;
419     
420        cout<<"Operation : "<<operation<<" isOnce "<<isOnceOperation<<endl;         
[219]421#define DECLARE_FUNCTOR(MType, mtype)              \
422   if  (operation.getValue().compare(#mtype) == 0) \
423   {                                               \
424      boost::shared_ptr<func::CFunctor>            \
425            foperation_(new C##MType(this->data)); \
426      this->foperation = foperation_;              \
427      return;                                      \
428   }
429   
430#include "functor_type.conf"
431         
432         ERROR("CField::solveOperation(void)",
433               << "[ operation = " << operation.getValue() << "]"
[421]434               << "The operation is not defined !");
[219]435      }
[436]436     
437
[219]438   }
439   
440   //----------------------------------------------------------------
[369]441/*
[219]442   void CField::fromBinary(StdIStream & is)
443   {
444      SuperClass::fromBinary(is);
445#define CLEAR_ATT(name_)\
[369]446      SuperClassAttribute::operator[](#name_)->reset()
[219]447
448         CLEAR_ATT(domain_ref);
449         CLEAR_ATT(axis_ref);
450#undef CLEAR_ATT
451
452   }
[369]453*/
[219]454   //----------------------------------------------------------------
455
456   void CField::solveGridReference(void)
457   {
[347]458      CDomain* domain;
459      CAxis* axis;
[219]460
461      if (!domain_ref.isEmpty())
462      {
[346]463         if (CDomain::has(domain_ref.getValue()))
464            domain = CDomain::get(domain_ref.getValue()) ;
[219]465         else
466            ERROR("CField::solveGridReference(void)",
[421]467                  << "Reference to the domain \'"
468                  << domain_ref.getValue() << "\' is wrong") ;
[219]469      }
470
471      if (!axis_ref.isEmpty())
472      {
[346]473         if (CAxis::has(axis_ref.getValue()))
474            axis = CAxis::get(axis_ref.getValue()) ;
[219]475         else
476            ERROR("CField::solveGridReference(void)",
[421]477                  << "Reference to the axis \'"
478                  << axis_ref.getValue() <<"\' is wrong") ;
[219]479      }
480
481      if (!grid_ref.isEmpty())
482      {
[346]483         if (CGrid::has(grid_ref.getValue()))
484            this->grid = CGrid::get(grid_ref.getValue()) ;
[219]485         else
486            ERROR("CField::solveGridReference(void)",
[421]487                  << "Reference to the grid \'"
488                  << grid_ref.getValue() << "\' is wrong");
[219]489      }
[418]490     
491      if (grid_ref.isEmpty() &&  domain_ref.isEmpty())
[219]492      {
493            ERROR("CField::solveGridReference(void)",
[421]494                  << "The horizontal domain for this field is not defined");
[418]495
496     }
497     
498     CType<string> goodDomain ;
499     CType<string> goodAxis ;
500     if (!grid_ref.isEmpty())
501     {
502       if (!grid->domain_ref.isEmpty()) goodDomain=grid->domain_ref ;
503       if (!grid->axis_ref.isEmpty()) goodAxis=grid->axis_ref ;
504     }
505     if (!domain_ref.isEmpty()) goodDomain=domain_ref ;
506     if (!axis_ref.isEmpty()) goodAxis=axis_ref ;
507     
508     
509     if (goodDomain.isEmpty()) 
510     {
[421]511       ERROR("CField::solveGridReference(void)", << "The horizontal domain for this field is not defined");
[418]512     }
513     else 
514     {
515       if (CDomain::has(goodDomain)) domain = CDomain::get(goodDomain) ;
[421]516       else ERROR("CField::solveGridReference(void)",<< "Reference to the domain \'"<<goodDomain.get() << "\' is wrong") ;
[418]517     }
518 
519     if (!goodAxis.isEmpty())
520     {
521       if (CAxis::has(goodAxis))  axis = CAxis::get(goodAxis) ;
[421]522       else  ERROR("CField::solveGridReference(void)", << "Reference to the axis \'"
523                  << goodAxis.get() <<"\' is wrong") ;
[418]524     } 
525   
526     bool nothingToDo=false ;
527     
528     if (!grid_ref.isEmpty())
529     {
530       if (!grid->domain_ref.isEmpty() && goodDomain.get() == grid->domain_ref.get())
531         if (goodAxis.isEmpty()) nothingToDo=true ;
532         else if (!grid->axis_ref.isEmpty()) 
533                 if (grid->axis_ref.get()==goodAxis.get()) nothingToDo=true ;
534     }
535     
536     if (!nothingToDo)
537     {
538       if (!goodAxis.isEmpty())
539       {
540         this->grid = CGrid::createGrid(domain, axis) ;
541         this->grid_ref.setValue(this->grid->getId());
542       }
543       else
544       {
545         this->grid = CGrid::createGrid(domain) ;
546         this->grid_ref.setValue(this->grid->getId());
547       }   
548     }
549
550     grid->solveReference() ;
[219]551   }
552
553
554   ///-------------------------------------------------------------------
555
556   template <>
557      void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
558   {
559      if (this->group_ref.isEmpty()) return;
560      StdString gref = this->group_ref.getValue();
561
[346]562      if (!CFieldGroup::has(gref))
[219]563         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
564               << "[ gref = " << gref << "]"
565               << " invalid group name !");
566
[347]567      CFieldGroup* group = CFieldGroup::get(gref);
568      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
[219]569
[347]570      std::vector<CField*> allChildren  = group->getAllChildren();
571      std::vector<CField*>::iterator
[219]572         it = allChildren.begin(), end = allChildren.end();
573     
574      for (; it != end; it++)
575      {
[347]576         CField* child = *it;
[346]577         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()) ;
578           
[219]579      }
580   }
[300]581   
[369]582   void CField::outputField(CArray<double,3>& fieldOut)
[300]583   {
[369]584      map<int, CArray<double,1>* >::iterator it;
[300]585      for(it=data_srv.begin();it!=data_srv.end();it++)
[369]586         grid->outputField(it->first,*it->second, fieldOut) ;
[300]587     
588   }
589   
[369]590   void CField::outputField(CArray<double,2>& fieldOut)
[300]591   {
[369]592      map<int, CArray<double,1>* >::iterator it;
[219]593
[300]594      for(it=data_srv.begin();it!=data_srv.end();it++)
595      {
[369]596         grid->outputField(it->first,*it->second, fieldOut) ;
[300]597      }
598   }
[219]599   ///-------------------------------------------------------------------
600
[335]601} // namespace xios
Note: See TracBrowser for help on using the repository browser.