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

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

Add possibility to make inheritance of attributes and reference before closing the context definition.
New fortran fonction : xios_solve inheritance()
After this call, the value of attribute have the inherited value of their parent.

YM

File size: 17.9 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      { /* Ne rien faire de plus */ }
27
28   CField::CField(const StdString & id)
29      : CObjectTemplate<CField>(id), CFieldAttributes()
30      , refObject(), baseRefObject()
31      , grid(), file()
32      , freq_operation(), freq_write()
33      , nstep(0)
34      , last_Write(), last_operation()
35      , foperation()
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   }
44
45   //----------------------------------------------------------------
46
47   bool CField::updateDataServer
48      (const CDate & currDate,
49       const std::deque< CArray<double, 1>* > storedClient)
50   {
51      const CDate opeDate      = *last_operation + freq_operation;
52      const CDate writeDate    = *last_Write     + freq_write; 
53     
54      if (opeDate <= currDate)
55      {
56         if (this->data.numElements() != this->grid->storeIndex[0]->numElements())
57         {
58            this->data.resize(this->grid->storeIndex[0] ->numElements());
59         } 
60         CArray<double,1> input(data.numElements()) ;
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    CContext* context = CContext::getCurrent() ;
98    CContextClient* client=context->client ;
99   
100    CEventClient event(getType(),EVENT_ID_UPDATE_DATA) ;
101   
102    map<int,CArray<int, 1>* >::iterator it ;
103    list<shared_ptr<CMessage> > list_msg ;
104    list< CArray<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      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)) ;
113      list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
114      list_data.push_back(new CArray<double,1>(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    for(list< CArray<double,1>* >::iterator it=list_data.begin();it!=list_data.end();it++) delete *it ;
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, CArray<int, 1>* >::iterator it=grid->out_i_fromClient.begin();it!=grid->out_i_fromClient.end();it++)
148      {
149        int rank=it->first ;
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])))) ;
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        CArray<double,1> data_tmp ;
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 (! 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      }
196  }
197   //----------------------------------------------------------------
198
199   void CField::setRelFile(CFile* _file)
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
212   CGrid* CField::getRelGrid(void) const
213   { 
214      return (this->grid); 
215   }
216
217   //----------------------------------------------------------------
218
219   CFile* CField::getRelFile(void) const
220   { 
221      return (this->file);
222   }
223   
224   StdSize CField::getNStep(void) const
225   {
226      return (this->nstep);
227   }
228   
229   void CField::incrementNStep(void)
230   {
231      this->nstep++;
232   }
233 
234   void CField::resetNStep(void)
235   {
236      this->nstep=0;
237   }
238
239   //----------------------------------------------------------------
240
241   CField* CField::getDirectFieldReference(void) const
242   {
243      if (this->field_ref.isEmpty())
244         return (this->getBaseFieldReference());
245
246      if (! CField::has(this->field_ref.getValue()))
247         ERROR("CField::getDirectFieldReference(void)",
248               << "[ ref_name = " << this->field_ref.getValue() << "]"
249               << " invalid field name !");
250
251      return (CField::get(this->field_ref.getValue()));
252   }
253
254   //----------------------------------------------------------------
255
256   CField* CField::getBaseFieldReference(void) const
257   { 
258      return (baseRefObject); 
259   }
260
261   //----------------------------------------------------------------
262
263   const std::vector<CField*>& CField::getAllReference(void) const 
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   
277   const CDuration & CField::getFreqOperation(void) const
278   {
279      return (this->freq_operation);
280   }
281   
282   //----------------------------------------------------------------
283   const CDuration & CField::getFreqWrite(void) const
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   { 
299     return (!this->field_ref.isEmpty()); 
300   }
301   
302   bool CField::isActive(void) const
303   { 
304      return (!this->refObject.empty()); 
305   }
306   //----------------------------------------------------------------
307   
308   CArray<double, 1> CField::getData(void) const
309   {
310      return(this->data);
311   }
312
313   //----------------------------------------------------------------
314
315   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
316   {
317      return(this->last_Write);
318   }
319
320   //----------------------------------------------------------------
321
322   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
323   {
324      return(this->last_operation);
325   }
326
327   //----------------------------------------------------------------
328
329   void CField::solveRefInheritance(bool apply)
330   {
331      std::set<CField *> sset;
332      CField* refer_sptr;
333      CField * refer_ptr = this;
334     
335      this->baseRefObject = CField::get(this);
336     
337      while (refer_ptr->hasDirectFieldReference())
338      {
339         refer_sptr = refer_ptr->getDirectFieldReference();
340         refer_ptr  = refer_sptr;
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, apply);
350         sset.insert(refer_ptr);
351         baseRefObject = refer_sptr;
352//ym         refObject.push_back(refer_sptr);
353      }
354   }
355
356   //----------------------------------------------------------------
357
358   void  CField::solveOperation(void)
359   {
360      using namespace func;
361       
362      StdString id = this->getBaseFieldReference()->getId();
363      CContext* context = CContext::getCurrent();
364     
365      if (freq_op.isEmpty()) freq_op=string("1ts") ;
366     
367      if (operation.isEmpty()  || this->file->output_freq.isEmpty())
368      {
369         ERROR("CField::solveOperation(void)",
370               << "[ id = " << id << "]"
371               << "Impossible to define an operation for this field !");
372      }
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      } 
383
384//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
385      if (context->hasServer)
386      {
387         this->freq_operation_srv =
388             CDuration::FromString(this->file->output_freq.getValue());
389         this->freq_write_srv     =
390             CDuration::FromString(this->file->output_freq.getValue());
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()));
397//         this->foperation_srv     =
398//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
399             
400         const CDuration toffset = this->freq_operation_srv - freq_offset_ - context->getCalendar()->getTimeStep(); 
401         *this->last_operation_srv   = *this->last_operation_srv - toffset; 
402      }
403     
404      if (context->hasClient)
405      {                 
406         this->freq_operation = CDuration::FromString(freq_op.getValue());
407         this->freq_write     = CDuration::FromString(this->file->output_freq.getValue());
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()));
412                       
413         const CDuration toffset = this->freq_operation - freq_offset_ - context->getCalendar()->getTimeStep(); 
414         *this->last_operation   = *this->last_operation - toffset; 
415     
416        if (operation.get()=="once") isOnceOperation=true ;
417        else isOnceOperation=false;
418        isFirstOperation=true;
419
420#define DECLARE_FUNCTOR(MType, mtype)              \
421   if  (operation.getValue().compare(#mtype) == 0) \
422   {                                               \
423      boost::shared_ptr<func::CFunctor>            \
424            foperation_(new C##MType(this->data)); \
425      this->foperation = foperation_;              \
426      return;                                      \
427   }
428   
429#include "functor_type.conf"
430         
431         ERROR("CField::solveOperation(void)",
432               << "[ operation = " << operation.getValue() << "]"
433               << "The operation is not defined !");
434      }
435     
436
437   }
438   
439   //----------------------------------------------------------------
440/*
441   void CField::fromBinary(StdIStream & is)
442   {
443      SuperClass::fromBinary(is);
444#define CLEAR_ATT(name_)\
445      SuperClassAttribute::operator[](#name_)->reset()
446
447         CLEAR_ATT(domain_ref);
448         CLEAR_ATT(axis_ref);
449#undef CLEAR_ATT
450
451   }
452*/
453   //----------------------------------------------------------------
454
455   void CField::solveGridReference(void)
456   {
457      CDomain* domain;
458      CAxis* axis;
459
460      if (!domain_ref.isEmpty())
461      {
462         if (CDomain::has(domain_ref.getValue()))
463            domain = CDomain::get(domain_ref.getValue()) ;
464         else
465            ERROR("CField::solveGridReference(void)",
466                  << "Reference to the domain \'"
467                  << domain_ref.getValue() << "\' is wrong") ;
468      }
469
470      if (!axis_ref.isEmpty())
471      {
472         if (CAxis::has(axis_ref.getValue()))
473            axis = CAxis::get(axis_ref.getValue()) ;
474         else
475            ERROR("CField::solveGridReference(void)",
476                  << "Reference to the axis \'"
477                  << axis_ref.getValue() <<"\' is wrong") ;
478      }
479
480      if (!grid_ref.isEmpty())
481      {
482         if (CGrid::has(grid_ref.getValue()))
483            this->grid = CGrid::get(grid_ref.getValue()) ;
484         else
485            ERROR("CField::solveGridReference(void)",
486                  << "Reference to the grid \'"
487                  << grid_ref.getValue() << "\' is wrong");
488      }
489     
490      if (grid_ref.isEmpty() &&  domain_ref.isEmpty())
491      {
492            ERROR("CField::solveGridReference(void)",
493                  << "The horizontal domain for this field is not defined");
494
495     }
496     
497     CType<string> goodDomain ;
498     CType<string> goodAxis ;
499     if (!grid_ref.isEmpty())
500     {
501       if (!grid->domain_ref.isEmpty()) goodDomain=grid->domain_ref ;
502       if (!grid->axis_ref.isEmpty()) goodAxis=grid->axis_ref ;
503     }
504     if (!domain_ref.isEmpty()) goodDomain=domain_ref ;
505     if (!axis_ref.isEmpty()) goodAxis=axis_ref ;
506     
507     
508     if (goodDomain.isEmpty()) 
509     {
510       ERROR("CField::solveGridReference(void)", << "The horizontal domain for this field is not defined");
511     }
512     else 
513     {
514       if (CDomain::has(goodDomain)) domain = CDomain::get(goodDomain) ;
515       else ERROR("CField::solveGridReference(void)",<< "Reference to the domain \'"<<goodDomain.get() << "\' is wrong") ;
516     }
517 
518     if (!goodAxis.isEmpty())
519     {
520       if (CAxis::has(goodAxis))  axis = CAxis::get(goodAxis) ;
521       else  ERROR("CField::solveGridReference(void)", << "Reference to the axis \'"
522                  << goodAxis.get() <<"\' is wrong") ;
523     } 
524   
525     bool nothingToDo=false ;
526     
527     if (!grid_ref.isEmpty())
528     {
529       if (!grid->domain_ref.isEmpty() && goodDomain.get() == grid->domain_ref.get())
530         if (goodAxis.isEmpty()) nothingToDo=true ;
531         else if (!grid->axis_ref.isEmpty()) 
532                 if (grid->axis_ref.get()==goodAxis.get()) nothingToDo=true ;
533     }
534     
535     if (!nothingToDo)
536     {
537       if (!goodAxis.isEmpty())
538       {
539         this->grid = CGrid::createGrid(domain, axis) ;
540         this->grid_ref.setValue(this->grid->getId());
541       }
542       else
543       {
544         this->grid = CGrid::createGrid(domain) ;
545         this->grid_ref.setValue(this->grid->getId());
546       }   
547     }
548
549     grid->solveReference() ;
550   }
551
552
553   ///-------------------------------------------------------------------
554
555   template <>
556      void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
557   {
558      if (this->group_ref.isEmpty()) return;
559      StdString gref = this->group_ref.getValue();
560
561      if (!CFieldGroup::has(gref))
562         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
563               << "[ gref = " << gref << "]"
564               << " invalid group name !");
565
566      CFieldGroup* group = CFieldGroup::get(gref);
567      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
568
569      std::vector<CField*> allChildren  = group->getAllChildren();
570      std::vector<CField*>::iterator
571         it = allChildren.begin(), end = allChildren.end();
572     
573      for (; it != end; it++)
574      {
575         CField* child = *it;
576         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()) ;
577           
578      }
579   }
580   
581   void CField::outputField(CArray<double,3>& fieldOut)
582   {
583      map<int, CArray<double,1>* >::iterator it;
584      for(it=data_srv.begin();it!=data_srv.end();it++)
585         grid->outputField(it->first,*it->second, fieldOut) ;
586     
587   }
588   
589   void CField::outputField(CArray<double,2>& fieldOut)
590   {
591      map<int, CArray<double,1>* >::iterator it;
592
593      for(it=data_srv.begin();it!=data_srv.end();it++)
594      {
595         grid->outputField(it->first,*it->second, fieldOut) ;
596      }
597   }
598   ///-------------------------------------------------------------------
599
600} // namespace xios
Note: See TracBrowser for help on using the repository browser.