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

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

Add xios_field_is_active functionnality

YM

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