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

Last change on this file since 600 was 600, checked in by rlacroix, 7 years ago

Grid: Remove scalar_grid attribute.

It always was for internal use only. This avoids having to remove part of the automatically generated Fortran interface.

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