source: vendor/nemo/current/NEMOGCM/EXTERNAL/XIOS/src/node/field.cpp @ 44

Last change on this file since 44 was 44, checked in by cholod, 12 years ago

Load NEMO_TMP into vendor/nemo/current.

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