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

Last change on this file since 619 was 619, checked in by mhnguyen, 9 years ago

Implementing the first prototype of filter

+) Create new class filter
+) Implement class for specific algorithm
+) Implement inversing algorithm

Test
+) On Curie
+) Grid with one axis: passed

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 40.1 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 "xios_spl.hpp"
11#include "type.hpp"
12#include "context_client.hpp"
13#include "context_server.hpp"
14#include <set>
15#include "axis_filter.hpp"
16#include "invert_algorithm.hpp"
17
18namespace xios{
19
20   /// ////////////////////// Définitions ////////////////////// ///
21
22   CField::CField(void)
23      : CObjectTemplate<CField>(), CFieldAttributes()
24      , refObject(), baseRefObject()
25      , grid(), file()
26      , freq_operation(), freq_write()
27      , nstep(0), nstepMax(0), isEOF(false)
28      , last_Write(), last_operation()
29      , foperation(), hasInstantData(false), hasExpression(false)
30      , active(false) , hasOutputFile(false),hasFieldOut(false), slotUpdateDate(NULL)
31      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false), filter(0)
32      , isReadDataRequestPending(false)
33      { setVirtualVariableGroup(); }
34
35   CField::CField(const StdString& id)
36      : CObjectTemplate<CField>(id), CFieldAttributes()
37      , refObject(), baseRefObject()
38      , grid(), file()
39      , freq_operation(), freq_write()
40      , nstep(0), nstepMax(0), isEOF(false)
41      , last_Write(), last_operation()
42      , foperation(), hasInstantData(false), hasExpression(false)
43      , active(false), hasOutputFile(false), hasFieldOut(false), slotUpdateDate(NULL)
44      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false), filter(0)
45      , isReadDataRequestPending(false)
46   { setVirtualVariableGroup(); }
47
48   CField::~CField(void)
49   {
50//      this->grid.reset();
51//      this->file.reset();
52      this->foperation.reset();
53      if (hasExpression) delete expression;
54      if (slotUpdateDate != NULL) delete slotUpdateDate;
55      if (0 != filter) delete filter;
56
57   }
58
59
60  //----------------------------------------------------------------
61
62   void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
63   {
64      this->vVariableGroup = newVVariableGroup;
65   }
66
67   void CField::setVirtualVariableGroup(void)
68   {
69      this->setVirtualVariableGroup(CVariableGroup::create());
70   }
71
72   CVariableGroup* CField::getVirtualVariableGroup(void) const
73   {
74      return this->vVariableGroup;
75   }
76
77
78   std::vector<CVariable*> CField::getAllVariables(void) const
79   {
80      return this->vVariableGroup->getAllChildren();
81   }
82
83   void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent)
84   {
85      SuperClassAttribute::setAttributes(parent, apply);
86      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
87   }
88   //----------------------------------------------------------------
89   //----------------------------------------------------------------
90
91   bool CField::updateDataServer
92      (const CDate& currDate,
93       const std::deque< CArray<double, 1>* > storedClient)
94   {
95      const CDate opeDate      = *last_operation + freq_operation;
96      const CDate writeDate    = *last_Write     + freq_write;
97
98      if (opeDate <= currDate)
99      {
100         if (this->data.numElements() != this->grid->storeIndex[0]->numElements())
101         {
102            this->data.resize(this->grid->storeIndex[0]->numElements());
103         }
104         CArray<double,1> input(data.numElements());
105         this->grid->inputFieldServer(storedClient, input);
106         (*this->foperation)(input);
107         *last_operation = currDate;
108      }
109      if (writeDate < (currDate + freq_operation))
110      {
111         this->foperation->final();
112         this->incrementNStep();
113         *last_Write = writeDate;
114         return true;
115      }
116      return false;
117   }
118
119  bool CField::dispatchEvent(CEventServer& event)
120  {
121    if (SuperClass::dispatchEvent(event)) return true;
122    else
123    {
124      switch(event.type)
125      {
126        case EVENT_ID_UPDATE_DATA :
127          recvUpdateData(event);
128          return true;
129          break;
130
131        case EVENT_ID_READ_DATA :
132          recvReadDataRequest(event);
133          return true;
134          break;
135
136        case EVENT_ID_READ_DATA_READY :
137          recvReadDataReady(event);
138          return true;
139          break;
140
141        case EVENT_ID_ADD_VARIABLE :
142          recvAddVariable(event);
143          return true;
144          break;
145
146        case EVENT_ID_ADD_VARIABLE_GROUP :
147          recvAddVariableGroup(event);
148          return true;
149          break;
150
151        default :
152          ERROR("bool CField::dispatchEvent(CEventServer& event)", << "Unknown Event");
153          return false;
154      }
155    }
156  }
157
158  void CField::sendUpdateData(void)
159  {
160    CContext* context = CContext::getCurrent();
161    CContextClient* client = context->client;
162
163    CEventClient event(getType(),EVENT_ID_UPDATE_DATA);
164
165    map<int,CArray<int, 1>* >::iterator it;
166    list<shared_ptr<CMessage> > list_msg;
167    list< CArray<double,1>* > list_data;
168
169    if (!grid->doGridHaveDataDistributed())
170    {
171       if (0 == client->clientRank)
172       {
173          for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
174          {
175            int rank=(*it).first ;
176            CArray<int,1>& index = *(it->second) ;
177                       std::cout << "rank " << index << std::endl;
178                       std::cout << "data " << data << std::endl;
179            CArray<double,1> data_tmp(index.numElements()) ;
180            for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
181
182            list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
183            list_data.push_back(new CArray<double,1>(data_tmp)) ;
184            *list_msg.back()<<getId()<<*list_data.back() ;
185            event.push(rank,1,*list_msg.back()) ;
186          }
187          client->sendEvent(event) ;
188       } else client->sendEvent(event);
189    }
190    else
191    {
192      for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
193      {
194        int rank=(*it).first ;
195        CArray<int,1>& index = *(it->second) ;
196        CArray<double,1> data_tmp(index.numElements()) ;
197        for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
198        list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
199        list_data.push_back(new CArray<double,1>(data_tmp)) ;
200        *list_msg.back()<<getId()<<*list_data.back() ;
201        event.push(rank,grid->nbSenders[rank],*list_msg.back()) ;
202      }
203      client->sendEvent(event) ;
204    }
205
206    for (list< CArray<double,1>* >::iterator it = list_data.begin(); it != list_data.end(); it++) delete *it;
207  }
208
209  void CField::recvUpdateData(CEventServer& event)
210  {
211    vector<int> ranks;
212    vector<CBufferIn*> buffers;
213
214    list<CEventServer::SSubEvent>::iterator it;
215    string fieldId;
216
217    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
218    {
219      int rank = it->rank;
220      CBufferIn* buffer = it->buffer;
221      *buffer >> fieldId;
222      ranks.push_back(rank);
223      buffers.push_back(buffer);
224    }
225    get(fieldId)->recvUpdateData(ranks,buffers);
226  }
227
228  void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
229  {
230    if (data_srv.empty())
231    {
232      for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
233      {
234        int rank = it->first;
235        CArray<double,1> data_tmp(it->second->numElements());
236        data_srv.insert( pair<int, CArray<double,1>* >(rank, new CArray<double,1>(data_tmp)));
237        foperation_srv.insert(pair<int,boost::shared_ptr<func::CFunctor> >(rank,boost::shared_ptr<func::CFunctor>(new func::CInstant(*data_srv[rank]))));
238      }
239    }
240
241    CContext* context = CContext::getCurrent();
242    const CDate& currDate = context->getCalendar()->getCurrentDate();
243    const CDate opeDate      = *last_operation_srv + freq_operation_srv;
244    const CDate writeDate    = *last_Write_srv     + freq_write_srv;
245
246    if (opeDate <= currDate)
247    {
248      for (int n = 0; n < ranks.size(); n++)
249      {
250        CArray<double,1> data_tmp;
251        *buffers[n] >> data_tmp;
252        (*foperation_srv[ranks[n]])(data_tmp);
253      }
254      *last_operation_srv = currDate;
255    }
256
257    if (writeDate < (currDate + freq_operation_srv))
258    {
259      for (int n = 0; n < ranks.size(); n++)
260      {
261        this->foperation_srv[ranks[n]]->final();
262      }
263
264      *last_Write_srv = writeDate;
265      writeField();
266      *lastlast_Write_srv = *last_Write_srv;
267    }
268  }
269
270  void CField::writeField(void)
271  {
272    if (!getRelFile()->allDomainEmpty)
273    {
274      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
275      {
276        getRelFile()->checkFile();
277        this->incrementNStep();
278        getRelFile()->getDataOutput()->writeFieldData(CField::get(this));
279      }
280    }
281  }
282
283  void CField::sendReadDataRequest(void)
284  {
285    CContext* context = CContext::getCurrent();
286    CContextClient* client = context->client;
287
288    CEventClient event(getType(), EVENT_ID_READ_DATA);
289    if (client->isServerLeader())
290    {
291      CMessage msg;
292      msg << getId();
293      const std::list<int>& ranks = client->getRanksServerLeader();
294      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
295        event.push(*itRank, 1, msg);
296      client->sendEvent(event);
297    }
298    else client->sendEvent(event);
299
300    lastDataRequestedFromServer = context->getCalendar()->getCurrentDate();
301    isReadDataRequestPending = true;
302  }
303
304  /*!
305  Send request new data read from file if need be, that is the current data is out-of-date.
306  \return true if and only if some data was requested
307  */
308  bool CField::sendReadDataRequestIfNeeded(void)
309  {
310    const CDate& currentDate = CContext::getCurrent()->getCalendar()->getCurrentDate();
311
312    bool requestData = (currentDate >= lastDataRequestedFromServer + file->output_freq.getValue());
313
314    if (requestData)
315      sendReadDataRequest();
316
317    return requestData;
318  }
319
320  void CField::recvReadDataRequest(CEventServer& event)
321  {
322    CBufferIn* buffer = event.subEvents.begin()->buffer;
323    StdString fieldId;
324    *buffer >> fieldId;
325    get(fieldId)->recvReadDataRequest();
326  }
327
328  void CField::recvReadDataRequest(void)
329  {
330    CContext* context = CContext::getCurrent();
331    CContextClient* client = context->client;
332
333    CEventClient event(getType(), EVENT_ID_READ_DATA_READY);
334    std::list<CMessage> msgs;
335
336    bool hasData = readField();
337
338    map<int, CArray<double,1>* >::iterator it;
339    for (it = data_srv.begin(); it != data_srv.end(); it++)
340    {
341      msgs.push_back(CMessage());
342      CMessage& msg = msgs.back();
343      msg << getId();
344      if (hasData)
345        msg << getNStep() - 1 << *it->second;
346      else
347        msg << size_t(-1);
348      event.push(it->first, grid->nbSenders[it->first], msg);
349    }
350    client->sendEvent(event);
351  }
352
353  bool CField::readField(void)
354  {
355    if (!getRelFile()->allDomainEmpty)
356    {
357      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
358      {
359        if (data_srv.empty())
360        {
361          for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
362            data_srv.insert(pair<int, CArray<double,1>*>(it->first, new CArray<double,1>(it->second->numElements())));
363        }
364
365        getRelFile()->checkFile();
366        this->incrementNStep();
367
368        if (!nstepMax)
369        {
370          nstepMax = getRelFile()->getDataInput()->getFieldNbRecords(CField::get(this));
371        }
372
373        if (getNStep() > nstepMax)
374          return false;
375
376        getRelFile()->getDataInput()->readFieldData(CField::get(this));
377      }
378    }
379
380    return true;
381  }
382
383  void CField::recvReadDataReady(CEventServer& event)
384  {
385    string fieldId;
386    vector<int> ranks;
387    vector<CBufferIn*> buffers;
388
389    list<CEventServer::SSubEvent>::iterator it;
390    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
391    {
392      ranks.push_back(it->rank);
393      CBufferIn* buffer = it->buffer;
394      *buffer >> fieldId;
395      buffers.push_back(buffer);
396    }
397    get(fieldId)->recvReadDataReady(ranks, buffers);
398  }
399
400  void CField::recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers)
401  {
402    CContext* context = CContext::getCurrent();
403    StdSize record;
404    for (int i = 0; i < ranks.size(); i++)
405    {
406      int rank = ranks[i];
407      *buffers[i] >> record;
408      isEOF = (record == size_t(-1));
409
410      if (!isEOF)
411      {
412        CArray<int,1>& index = *grid->storeIndex_toSrv[rank];
413        CArray<double,1> data_tmp(index.numElements());
414        *buffers[i] >> data_tmp;
415        for (int n = 0; n < data_tmp.numElements(); n++)
416          instantData(index(n)) = data_tmp(n);
417      }
418      else
419        break;
420    }
421
422    if (!isEOF)
423    {
424      for (list< pair<CField*, int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it)
425        it->first->setSlot(it->second);
426
427      if (!hasExpression) // Should be always true ?
428      {
429        const std::vector<CField*>& refField = getAllReference();
430        std::vector<CField*>::const_iterator it = refField.begin(), end = refField.end();
431
432        for (; it != end; it++) (*it)->setDataFromExpression(instantData);
433        if (hasFieldOut) updateDataFromExpression(instantData);
434      }
435    }
436
437    isReadDataRequestPending = false;
438  }
439
440   //----------------------------------------------------------------
441
442   void CField::setRelFile(CFile* _file)
443   {
444      this->file = _file;
445      hasOutputFile = true;
446   }
447
448   //----------------------------------------------------------------
449
450   StdString CField::GetName(void)    { return StdString("field"); }
451   StdString CField::GetDefName(void) { return CField::GetName(); }
452   ENodeType CField::GetType(void)    { return eField; }
453
454   //----------------------------------------------------------------
455
456   CGrid* CField::getRelGrid(void) const
457   {
458      return this->grid;
459   }
460
461   //----------------------------------------------------------------
462
463   CFile* CField::getRelFile(void) const
464   {
465      return this->file;
466   }
467
468   StdSize CField::getNStep(void) const
469   {
470      return this->nstep;
471   }
472
473   void CField::incrementNStep(void)
474   {
475      this->nstep++;
476   }
477
478   void CField::resetNStep(void)
479   {
480      this->nstep = 0;
481   }
482
483   void CField::resetNStepMax(void)
484   {
485      this->nstepMax = 0;
486   }
487
488   //----------------------------------------------------------------
489
490   const CDuration& CField::getFreqOperation(void) const
491   {
492      return this->freq_operation;
493   }
494
495   //----------------------------------------------------------------
496
497   const CDuration& CField::getFreqWrite(void) const
498   {
499      return this->freq_write;
500   }
501
502   //----------------------------------------------------------------
503
504   boost::shared_ptr<func::CFunctor> CField::getFieldOperation(void) const
505   {
506      return this->foperation;
507   }
508
509   bool CField::isActive(void) const
510   {
511      return !this->refObject.empty();
512   }
513
514   //----------------------------------------------------------------
515
516   CArray<double, 1> CField::getData(void) const
517   {
518      return(this->data);
519   }
520
521   //----------------------------------------------------------------
522
523   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
524   {
525      return(this->last_Write);
526   }
527
528   //----------------------------------------------------------------
529
530   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
531   {
532      return(this->last_operation);
533   }
534
535   void CField::solveAllReferenceEnabledField(bool doSending2Sever)
536   {
537     CContext* context = CContext::getCurrent();
538     if (!areAllReferenceSolved)
539     {
540        areAllReferenceSolved = true;
541        if (context->hasClient)
542        {
543          solveRefInheritance(true);
544          solveBaseReference();
545        }
546
547        solveOperation();
548        solveGridReference();
549     }
550     solveGridDomainAxisRef(doSending2Sever);
551     if (context->hasClient)
552     {
553       solveTransformedGrid();
554     }
555     solveCheckMaskIndex(doSending2Sever);
556   }
557
558   std::map<int, StdSize> CField::getGridDataSize()
559   {
560     return grid->getConnectedServerDataSize();
561   }
562
563   void CField::buildAllExpressionEnabledField()
564   {
565     if (!areAllReferenceSolved) solveAllReferenceEnabledField(true);
566     if (!areAllExpressionBuilt)
567     {
568       areAllExpressionBuilt = true;
569       if (hasDirectFieldReference() && (grid_ref.isEmpty())) baseRefObject->buildAllExpressionEnabledField();
570       buildExpression();
571       active = true;
572     }
573   }
574
575   //----------------------------------------------------------------
576
577   void  CField::solveOperation(void)
578   {
579      using namespace func;
580
581      if (!hasOutputFile && !hasFieldOut) return;
582
583      StdString id;
584      if (hasId()) id = getId();
585      else if (!name.isEmpty()) id = name;
586      else if (hasDirectFieldReference()) id = baseRefObject->getId();
587
588      CContext* context = CContext::getCurrent();
589
590      if (freq_op.isEmpty()) freq_op.setValue(TimeStep);
591
592      if (operation.isEmpty())
593      {
594         ERROR("CField::solveOperation(void)",
595               << "[ id = " << id << "]"
596               << "Impossible to define an operation for this field !");
597      }
598
599      if (freq_offset.isEmpty())
600        freq_offset.setValue(NoneDu);
601
602//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
603      if (context->hasServer)
604      {
605         if (hasOutputFile)
606         {
607           this->freq_operation_srv = this->file->output_freq.getValue();
608           this->freq_write_srv = this->file->output_freq.getValue();
609         }
610         this->lastlast_Write_srv = boost::shared_ptr<CDate>
611                        (new CDate(context->getCalendar()->getInitDate()));
612         this->last_Write_srv     = boost::shared_ptr<CDate>
613                        (new CDate(context->getCalendar()->getInitDate()));
614         this->last_operation_srv = boost::shared_ptr<CDate>
615                        (new CDate(context->getCalendar()->getInitDate()));
616//         this->foperation_srv     =
617//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
618
619         if (hasOutputFile)
620         {
621           const CDuration toffset = this->freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
622           *this->last_operation_srv   = *this->last_operation_srv - toffset;
623         }
624      }
625
626//      if (context->hasClient)
627//      {
628         this->freq_operation = freq_op.getValue();
629         if (hasOutputFile) this->freq_write = this->file->output_freq.getValue();
630         if (hasFieldOut)
631         {
632           this->freq_write = this->fieldOut->freq_op.getValue();
633         }
634         this->last_Write     = boost::shared_ptr<CDate>
635                        (new CDate(context->getCalendar()->getInitDate()));
636         this->last_operation = boost::shared_ptr<CDate>
637                        (new CDate(context->getCalendar()->getInitDate()));
638
639         const CDuration toffset = this->freq_operation - freq_offset.getValue() - context->getCalendar()->getTimeStep();
640         *this->last_operation   = *this->last_operation - toffset;
641
642         lastDataRequestedFromServer.setRelCalendar(*context->getCalendar());
643
644        if (operation.get() == "once") isOnceOperation = true;
645        else isOnceOperation = false;
646        isFirstOperation = true;
647
648#define DECLARE_FUNCTOR(MType, mtype) \
649   if (operation.getValue().compare(#mtype) == 0) \
650   { \
651      if (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true) \
652      { \
653        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data,default_value)); \
654        this->foperation = foperation_; \
655      } \
656      else \
657      { \
658        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
659        this->foperation = foperation_; \
660      } \
661      return; \
662   }
663
664#include "functor_type.conf"
665
666         ERROR("CField::solveOperation(void)",
667               << "[ operation = " << operation.getValue() << "]"
668               << "The operation is not defined !");
669//      }
670   }
671
672   //----------------------------------------------------------------
673/*
674   void CField::fromBinary(StdIStream& is)
675   {
676      SuperClass::fromBinary(is);
677#define CLEAR_ATT(name_)\
678      SuperClassAttribute::operator[](#name_)->reset()
679
680         CLEAR_ATT(domain_ref);
681         CLEAR_ATT(axis_ref);
682#undef CLEAR_ATT
683
684   }
685*/
686   //----------------------------------------------------------------
687
688   void CField::solveGridReference(void)
689   {
690      CDomain* domain;
691      CAxis* axis;
692      std::vector<CDomain*> vecDom;
693      std::vector<CAxis*> vecAxis;
694      std::vector<std::string> domList, axisList;
695
696      if (!domain_ref.isEmpty())
697      {
698         if (CDomain::has(domain_ref.getValue()))
699         {
700           domain = CDomain::get(domain_ref.getValue());
701           vecDom.push_back(domain);
702         }
703         else
704            ERROR("CField::solveGridReference(void)",
705                  << "Reference to the domain \'"
706                  << domain_ref.getValue() << "\' is wrong");
707      }
708
709      if (!axis_ref.isEmpty())
710      {
711         if (CAxis::has(axis_ref.getValue()))
712         {
713           axis = CAxis::get(axis_ref.getValue());
714           vecAxis.push_back(axis);
715         }
716         else
717            ERROR("CField::solveGridReference(void)",
718                  << "Reference to the axis \'"
719                  << axis_ref.getValue() <<"\' is wrong");
720      }
721
722      if (!grid_ref.isEmpty())
723      {
724         if (CGrid::has(grid_ref.getValue()))
725         {
726           this->grid = CGrid::get(grid_ref.getValue());
727           domList = grid->getDomainList();
728           axisList = grid->getAxisList();
729           if (domList.empty() && axisList.empty())
730           {
731             this->grid = CGrid::createGrid(vecDom, vecAxis);
732           }
733         }
734         else
735            ERROR("CField::solveGridReference(void)",
736                  << "Reference to the grid \'"
737                  << grid_ref.getValue() << "\' is wrong");
738      }
739      else
740      {
741         this->grid = CGrid::createGrid(vecDom, vecAxis);
742      }
743
744      if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty())
745      {
746            ERROR("CField::solveGridReference(void)",
747                  << "At least one dimension must be defined for this field.");
748      }
749   }
750
751   void CField::solveGridDomainAxisRef(bool checkAtt)
752   {
753     grid->solveDomainAxisRef(checkAtt);
754   }
755
756   void CField::solveCheckMaskIndex(bool doSendingIndex)
757   {
758     grid->checkMaskIndex(doSendingIndex);
759   }
760
761   CGrid* CField::getGridRefOfBaseReference()
762   {
763     solveRefInheritance(true);
764     solveBaseReference();
765     baseRefObject->solveGridReference();
766
767     return baseRefObject->grid;
768   }
769
770   void CField::solveTransformedGrid()
771   {
772     if (!grid_ref.isEmpty() && (!field_ref.isEmpty()))
773     {
774       CField* fieldRef  = this;
775       CGrid* gridRefOfFieldRef = 0;
776       while (fieldRef->hasDirectFieldReference())
777       {
778         if ((!(fieldRef->grid_ref.isEmpty())) &&
779             (fieldRef->grid_ref.getValue() != grid_ref.getValue()))
780         {
781           gridRefOfFieldRef = fieldRef->getGridRefOfBaseReference();
782           fieldRef->addReference(this);
783           fieldRef->solveGridDomainAxisRef(false);
784           fieldRef->solveCheckMaskIndex(false);
785           break;
786         }
787         CField* tmp = fieldRef->getDirectFieldReference();
788         fieldRef = tmp;
789       }
790
791       if ((0 == gridRefOfFieldRef) &&
792           (!(fieldRef->grid_ref.isEmpty())) &&
793           (fieldRef->grid_ref.getValue() != grid_ref.getValue()))
794       {
795         gridRefOfFieldRef = fieldRef->getGridRefOfBaseReference();
796         fieldRef->addReference(this);
797         fieldRef->solveGridDomainAxisRef(false);
798         fieldRef->solveCheckMaskIndex(false);
799       }
800
801       CGrid* relGridRef = CGrid::get(grid_ref.getValue());
802       if ((0 != gridRefOfFieldRef) && (relGridRef != gridRefOfFieldRef) && (!(relGridRef->isTransformed())))
803       {
804         gridRefOfFieldRef->transformGrid(relGridRef);
805         filterSources_.push_back(fieldRef);
806         transformations_ = relGridRef->getTransformations();
807         switch (gridRefOfFieldRef->getGridElementType()) {
808         case CGrid::GRID_ONLY_AXIS:
809           filter = new CAxisFilter(gridRefOfFieldRef, relGridRef);
810           break;
811         default:
812           break;
813         }
814         setAlgorithms();
815       }
816     }
817   }
818
819
820  void CField::setAlgorithms()
821  {
822    std::vector<ETransformationType>::iterator itTrans  = transformations_.begin(),
823                                               iteTrans = transformations_.end();
824    std::set<ETransformationType> tmp;
825    for (; itTrans != iteTrans; ++itTrans)
826    {
827      if (tmp.end() == tmp.find(*itTrans))
828      {
829        switch (*itTrans) {
830        case eInverse:
831          algorithms_.push_back(new CInvertAlgorithm());
832          break;
833        default:
834          break;
835        }
836      }
837      tmp.insert(*itTrans);
838    }
839  }
840
841   const std::vector<CField*>& CField::getFilterSources()
842   {
843     return filterSources_;
844   }
845
846   void CField::applyFilter()
847   {
848     filter->setInputs(filterSources_);
849     filter->setOutput(this);
850     filter->apply(algorithms_);
851
852   }
853
854   ///-------------------------------------------------------------------
855
856   template <>
857   void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
858   {
859      if (this->group_ref.isEmpty()) return;
860      StdString gref = this->group_ref.getValue();
861
862      if (!CFieldGroup::has(gref))
863         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
864               << "[ gref = " << gref << "]"
865               << " invalid group name !");
866
867      CFieldGroup* group = CFieldGroup::get(gref);
868      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
869
870      std::vector<CField*> allChildren  = group->getAllChildren();
871      std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end();
872
873      for (; it != end; it++)
874      {
875         CField* child = *it;
876         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId());
877
878      }
879   }
880
881   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
882   {
883     map<int, CArray<double,1>* >::iterator it;
884     for (it = data_srv.begin(); it != data_srv.end(); it++) *it->second = (*it->second - addOffset) / scaleFactor;
885   }
886
887   void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset)
888   {
889     map<int, CArray<double,1>* >::iterator it;
890     for (it = data_srv.begin(); it != data_srv.end(); it++) *it->second = *it->second * scaleFactor + addOffset;
891   }
892
893   void CField::outputField(CArray<double,3>& fieldOut)
894   {
895      map<int, CArray<double,1>* >::iterator it;
896      for (it = data_srv.begin(); it != data_srv.end(); it++)
897      {
898        grid->outputField(it->first,*it->second, fieldOut.dataFirst());
899      }
900   }
901
902   void CField::outputField(CArray<double,2>& fieldOut)
903   {
904      map<int, CArray<double,1>* >::iterator it;
905      for(it=data_srv.begin();it!=data_srv.end();it++)
906      {
907         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
908      }
909   }
910
911   void CField::outputField(CArray<double,1>& fieldOut)
912   {
913      map<int, CArray<double,1>* >::iterator it;
914
915      for (it = data_srv.begin(); it != data_srv.end(); it++)
916      {
917         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
918      }
919   }
920
921   void CField::inputField(CArray<double,3>& fieldOut)
922   {
923      map<int, CArray<double,1>*>::iterator it;
924      for (it = data_srv.begin(); it != data_srv.end(); it++)
925      {
926        grid->inputField(it->first, fieldOut.dataFirst(), *it->second);
927      }
928   }
929
930   void CField::inputField(CArray<double,2>& fieldOut)
931   {
932      map<int, CArray<double,1>*>::iterator it;
933      for(it = data_srv.begin(); it != data_srv.end(); it++)
934      {
935         grid->inputField(it->first, fieldOut.dataFirst(), *it->second);
936      }
937   }
938
939   void CField::inputField(CArray<double,1>& fieldOut)
940   {
941      map<int, CArray<double,1>*>::iterator it;
942      for (it = data_srv.begin(); it != data_srv.end(); it++)
943      {
944         grid->inputField(it->first, fieldOut.dataFirst(), *it->second);
945      }
946   }
947
948   ///-------------------------------------------------------------------
949
950   void CField::parse(xml::CXMLNode& node)
951   {
952      SuperClass::parse(node);
953      if (!node.getContent(this->content))
954      {
955        if (node.goToChildElement())
956        {
957          do
958          {
959            if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node);
960          } while (node.goToNextElement());
961          node.goToParentElement();
962        }
963      }
964    }
965
966  CArray<double,1>* CField::getInstantData(void)
967  {
968    if (!hasInstantData)
969    {
970      instantData.resize(grid->storeIndex_client.numElements());
971      hasInstantData = true;
972    }
973    return &instantData;
974  }
975
976  void CField::addDependency(CField* field, int slotId)
977  {
978    fieldDependency.push_back(pair<CField*,int>(field,slotId));
979  }
980
981  void CField::buildExpression(void)
982  {
983    if (content.size() > 0)
984    {
985      CSimpleNodeExpr* simpleExpr = parseExpr(content+'\0');
986      expression = CFieldNode::newNode(simpleExpr);
987      delete simpleExpr;
988      set<string> instantFieldIds;
989      map<string,CField*> associatedInstantFieldIds;
990      expression->getInstantFieldIds(instantFieldIds);
991      for (set<string>::iterator it = instantFieldIds.begin(); it != instantFieldIds.end(); ++it)
992      {
993        if (*it != "this")
994        {
995          if (CField::has(*it))
996          {
997            CField* field = CField::get(*it);
998//            field->processEnabledField();
999            field->buildAllExpressionEnabledField();
1000            associatedInstantFieldIds[*it] = field;
1001          }
1002          else  ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
1003        }
1004      }
1005
1006      set<string> averageFieldIds;
1007      map<string,CField*> associatedAverageFieldIds;
1008
1009      expression->getAverageFieldIds(averageFieldIds);
1010      for (set<string>::iterator it = averageFieldIds.begin(); it != averageFieldIds.end(); ++it)
1011      {
1012        if (CField::has(*it))
1013        {
1014           CFieldGroup* root = CFieldGroup::get("field_definition");
1015           CField* averageField = root->createChild();
1016           CField* instantField = root->createChild();
1017           averageField->field_ref = *it;
1018           averageField->hasFieldOut = true;
1019           averageField->fieldOut = instantField;
1020           instantField->freq_op = freq_op;
1021//           averageField-> processEnabledField();
1022           averageField->buildAllExpressionEnabledField();
1023           instantField->SuperClassAttribute::setAttributes(averageField, true);
1024           instantField->field_ref.reset();
1025           instantField->operation.reset();
1026
1027//           instantField-> processEnabledField();
1028           instantField->buildAllExpressionEnabledField();
1029           associatedAverageFieldIds[*it] = instantField;
1030        }
1031        else ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
1032      }
1033
1034      expression->reduce(this,associatedInstantFieldIds,associatedAverageFieldIds);
1035
1036      slots.resize(instantFieldIds.size() + averageFieldIds.size());
1037      resetSlots();
1038      int slotId = 0;
1039      set<CField*> fields;
1040      expression->getFields(fields);
1041      for (set<CField*>::iterator it = fields.begin(); it != fields.end(); ++it, ++slotId) (*it)->addDependency(this,slotId);
1042      hasExpression = true;
1043    }
1044  }
1045
1046  void CField::resetSlots(void)
1047  {
1048    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) *it = false;
1049  }
1050
1051  bool CField::slotsFull(void)
1052  {
1053    bool ret = true;
1054    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) ret &= *it;
1055    return ret;
1056  }
1057
1058  void CField::setSlot(int slotId)
1059  {
1060    CContext* context = CContext::getCurrent();
1061    const CDate& currDate = context->getCalendar()->getCurrentDate();
1062    if (slotUpdateDate == NULL || currDate != *slotUpdateDate)
1063    {
1064      resetSlots();
1065      if (slotUpdateDate == NULL) slotUpdateDate = new CDate(currDate);
1066      else *slotUpdateDate = currDate;
1067    }
1068    slots[slotId] = true;
1069    if (slotsFull())
1070    {
1071      CArray<double,1> expr(expression->compute());
1072
1073      if (hasInstantData)
1074      {
1075        instantData = expr;
1076        for (list< pair<CField *,int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it)
1077          if (it->first != this) it->first->setSlot(it->second);
1078      }
1079
1080      if (hasOutputFile) updateDataFromExpression(expr);
1081
1082      const std::vector<CField*>& refField = getAllReference();
1083      for (std::vector<CField*>::const_iterator it = refField.begin(); it != refField.end(); it++)
1084      {
1085        if (!(*it)->hasExpression)
1086          (*it)->setDataFromExpression(expr);
1087      }
1088    }
1089  }
1090
1091   /*!
1092     This function retrieves Id of corresponding domain_ref and axis_ref (if any)
1093   of a field. In some cases, only domain exists but axis doesn't
1094   \return pair of Domain and Axis id
1095   */
1096   const std::pair<StdString,StdString>& CField::getRefDomainAxisIds()
1097   {
1098     CGrid* cgPtr = getRelGrid();
1099     if (NULL != cgPtr)
1100     {
1101       std::vector<StdString>::iterator it;
1102       if (!domain_ref.isEmpty())
1103       {
1104         std::vector<StdString> domainList = cgPtr->getDomainList();
1105         it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue());
1106         if (domainList.end() != it) domAxisIds_.first = *it;
1107       }
1108
1109       if (!axis_ref.isEmpty())
1110       {
1111         std::vector<StdString> axisList = cgPtr->getAxisList();
1112         it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue());
1113         if (axisList.end() != it) domAxisIds_.second = *it;
1114       }
1115     }
1116     return (domAxisIds_);
1117   }
1118
1119   CVariable* CField::addVariable(const string& id)
1120   {
1121     return vVariableGroup->createChild(id);
1122   }
1123
1124   CVariableGroup* CField::addVariableGroup(const string& id)
1125   {
1126     return vVariableGroup->createChildGroup(id);
1127   }
1128
1129   void CField::sendAddAllVariables()
1130   {
1131     if (!getAllVariables().empty())
1132     {
1133       // Firstly, it's necessary to add virtual variable group
1134       sendAddVariableGroup(getVirtualVariableGroup()->getId());
1135
1136       // Okie, now we can add to this variable group
1137       std::vector<CVariable*> allVar = getAllVariables();
1138       std::vector<CVariable*>::const_iterator it = allVar.begin();
1139       std::vector<CVariable*>::const_iterator itE = allVar.end();
1140
1141       for (; it != itE; ++it)
1142       {
1143         this->sendAddVariable((*it)->getId());
1144         (*it)->sendAllAttributesToServer();
1145         (*it)->sendValue();
1146       }
1147     }
1148   }
1149
1150   void CField::sendAddVariable(const string& id)
1151   {
1152    CContext* context = CContext::getCurrent();
1153
1154    if (!context->hasServer)
1155    {
1156       CContextClient* client = context->client;
1157
1158       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
1159       if (client->isServerLeader())
1160       {
1161         CMessage msg;
1162         msg << this->getId();
1163         msg << id;
1164         const std::list<int>& ranks = client->getRanksServerLeader();
1165         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1166           event.push(*itRank,1,msg);
1167         client->sendEvent(event);
1168       }
1169       else client->sendEvent(event);
1170    }
1171   }
1172
1173   void CField::sendAddVariableGroup(const string& id)
1174   {
1175    CContext* context = CContext::getCurrent();
1176    if (!context->hasServer)
1177    {
1178       CContextClient* client = context->client;
1179
1180       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP);
1181       if (client->isServerLeader())
1182       {
1183         CMessage msg;
1184         msg << this->getId();
1185         msg << id;
1186         const std::list<int>& ranks = client->getRanksServerLeader();
1187         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1188           event.push(*itRank,1,msg);
1189         client->sendEvent(event);
1190       }
1191       else client->sendEvent(event);
1192    }
1193   }
1194
1195   void CField::recvAddVariable(CEventServer& event)
1196   {
1197
1198      CBufferIn* buffer = event.subEvents.begin()->buffer;
1199      string id;
1200      *buffer >> id;
1201      get(id)->recvAddVariable(*buffer);
1202   }
1203
1204   void CField::recvAddVariable(CBufferIn& buffer)
1205   {
1206      string id;
1207      buffer >> id;
1208      addVariable(id);
1209   }
1210
1211   void CField::recvAddVariableGroup(CEventServer& event)
1212   {
1213
1214      CBufferIn* buffer = event.subEvents.begin()->buffer;
1215      string id;
1216      *buffer >> id;
1217      get(id)->recvAddVariableGroup(*buffer);
1218   }
1219
1220   void CField::recvAddVariableGroup(CBufferIn& buffer)
1221   {
1222      string id;
1223      buffer >> id;
1224      addVariableGroup(id);
1225   }
1226
1227   DEFINE_REF_FUNC(Field,field)
1228
1229//  void CField::addReference(CField* field)
1230//  {
1231//    refObject.push_back(field);
1232//  }
1233//
1234//   //----------------------------------------------------------------
1235//
1236//   bool CField::hasDirectFieldReference(void) const
1237//   {
1238//     return !this->field_ref.isEmpty();
1239//   }
1240//
1241//   //----------------------------------------------------------------
1242//
1243//   const StdString& CField::getBaseFieldId(void) const
1244//   {
1245//      return this->getBaseFieldReference()->getId();
1246//   }
1247//
1248//   //----------------------------------------------------------------
1249//
1250//   /*!
1251//   \brief Get pointer to direct field to which the current field refers.
1252//   */
1253//   CField* CField::getDirectFieldReference(void) const
1254//   {
1255//      if (this->field_ref.isEmpty())
1256//         return this->getBaseFieldReference();
1257//
1258//      if (!CField::has(this->field_ref.getValue()))
1259//         ERROR("CField::getDirectFieldReference(void)",
1260//               << "[ ref_name = " << this->field_ref.getValue() << "]"
1261//               << " invalid field name !");
1262//
1263//      return CField::get(this->field_ref.getValue());
1264//   }
1265//
1266//   //----------------------------------------------------------------
1267//
1268//   CField* CField::getBaseFieldReference(void) const
1269//   {
1270//      return baseRefObject;
1271//   }
1272//
1273//   //----------------------------------------------------------------
1274//
1275//   const std::vector<CField*>& CField::getAllReference(void) const
1276//   {
1277//      return refObject;
1278//   }
1279//
1280//   /*!
1281//   \brief Searching for all reference of a field
1282//   If a field refers to (an)other field(s), we will search for all its referenced parents.
1283//   Moreover, if any father, direct or indirect (e.g: two levels up), has non-empty attributes,
1284//   all its attributes will be added to the current field
1285//   \param [in] apply Flag to specify whether current field uses attributes of its father
1286//               in case the attribute is empty (true) or its attributes are replaced by ones of its father (false)
1287//   */
1288//   void CField::solveRefInheritance(bool apply)
1289//   {
1290//      std::set<CField *> sset;
1291//      CField* refer_sptr;
1292//      CField* refer_ptr = this;
1293//
1294//      while (refer_ptr->hasDirectFieldReference())
1295//      {
1296//         refer_sptr = refer_ptr->getDirectFieldReference();
1297//         refer_ptr  = refer_sptr;
1298//
1299//         if(sset.end() != sset.find(refer_ptr))
1300//         {
1301//            DEBUG (<< "Circular dependency stopped for field object on "
1302//                   << "\"" + refer_ptr->getId() + "\" !");
1303//            break;
1304//         }
1305//
1306//         SuperClassAttribute::setAttributes(refer_ptr, apply);
1307//         sset.insert(refer_ptr);
1308//      }
1309//   }
1310//
1311//   /*!
1312//   \brief Only on SERVER side. Remove all field_ref from current field
1313//   On creating a new field on server side, redundant "field_ref" is still kept in the attribute list
1314//   of the current field. This function removes this from current field
1315//   */
1316//   void CField::removeRefInheritance()
1317//   {
1318//     if (this->field_ref.isEmpty()) return;
1319//     this->clearAttribute("field_ref");
1320//   }
1321//
1322//   void CField::solveBaseReference(void)
1323//   {
1324//      std::set<CField *> sset;
1325//      CField* refer_sptr;
1326//      CField* refer_ptr = this;
1327//
1328//      if (this->hasDirectFieldReference())  baseRefObject = getDirectFieldReference();
1329//      else  baseRefObject = CField::get(this);
1330//
1331//      while (refer_ptr->hasDirectFieldReference())
1332//      {
1333//         refer_sptr = refer_ptr->getDirectFieldReference();
1334//         refer_ptr  = refer_sptr;
1335//
1336//         if(sset.end() != sset.find(refer_ptr))
1337//         {
1338//            DEBUG (<< "Circular dependency stopped for field object on "
1339//                   << "\"" + refer_ptr->getId() + "\" !");
1340//            break;
1341//         }
1342//
1343//         sset.insert(refer_ptr);
1344//      }
1345//
1346//      if (hasDirectFieldReference()) baseRefObject->addReference(this);
1347//   }
1348} // namespace xios
Note: See TracBrowser for help on using the repository browser.