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

Last change on this file since 621 was 621, checked in by mhnguyen, 6 years ago

Implementing generic transformation algorithm (local commit)

+) Change a little bit to make sure everything work in order

Test
+) test_new_features passe with inverse

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