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

Last change on this file since 624 was 624, checked in by mhnguyen, 8 years ago

Final tests of zoom and inverse on axis

+) Modify test_client and test_complete to work with new grid definition
+) Correct some bugs causing memory leak
+) Clean abundant code
+) Add more comments to new files

Test
+) On Curie
+) test_client and test_complete pass with correct results

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