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

Last change on this file since 345 was 345, checked in by ymipsl, 12 years ago

removed "tree" namespace

YM

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