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

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

Change namespace xmlioserver -> xios

YM

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