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

Last change on this file since 598 was 598, checked in by rlacroix, 9 years ago

Add the infrastructure to request fields from the server.

This will be used to read input files so add a new file attribute mode to define whether data is written or read from a file.

Currently the data is not actually read and random data is transfered for those fields in read mode.

  • 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: 35.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
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)
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)
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) //      if (! grid->domain->isEmpty() || 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    // TODO: Read the data from the file
332    if (data_srv.empty())
333    {
334      for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
335        data_srv.insert( pair<int, CArray<double,1>* >(it->first, new CArray<double,1>(it->second->numElements())));
336    }
337
338    map<int, CArray<double,1>* >::iterator it;
339    for (it = data_srv.begin(); it != data_srv.end(); it++)
340    {
341      msgs.push_back(CMessage());
342      CMessage& msg = msgs.back();
343      msg << getId() << getNStep() << *it->second;
344      event.push(it->first, grid->nbSenders[it->first], msg);
345    }
346    client->sendEvent(event);
347
348    incrementNStep();
349  }
350
351  void CField::recvReadDataReady(CEventServer& event)
352  {
353    string fieldId;
354    vector<int> ranks;
355    vector<CBufferIn*> buffers;
356
357    list<CEventServer::SSubEvent>::iterator it;
358    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
359    {
360      ranks.push_back(it->rank);
361      CBufferIn* buffer = it->buffer;
362      *buffer >> fieldId;
363      buffers.push_back(buffer);
364    }
365    get(fieldId)->recvReadDataReady(ranks, buffers);
366  }
367
368  void CField::recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers)
369  {
370    CContext* context = CContext::getCurrent();
371    StdSize record;
372    for (int i = 0; i < ranks.size(); i++)
373    {
374      int rank = ranks[i];
375      CArray<int,1>& index = *grid->storeIndex_toSrv[rank];
376      CArray<double,1> data_tmp(index.numElements());
377      *buffers[i] >> record >> data_tmp;
378
379      for (int n = 0; n < data_tmp.numElements(); n++)
380        instantData(index(n)) = data_tmp(n);
381    }
382
383    for (list< pair<CField*, int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it)
384      it->first->setSlot(it->second);
385
386    if (!hasExpression) // Should be always true ?
387    {
388      const std::vector<CField*>& refField = getAllReference();
389      std::vector<CField*>::const_iterator it = refField.begin(), end = refField.end();
390
391      for (; it != end; it++) (*it)->setDataFromExpression(instantData);
392      if (hasFieldOut) updateDataFromExpression(instantData);
393    }
394
395    isReadDataRequestPending = false;
396  }
397
398   //----------------------------------------------------------------
399
400   void CField::setRelFile(CFile* _file)
401   {
402      this->file = _file;
403      hasOutputFile = true;
404   }
405
406   //----------------------------------------------------------------
407
408   StdString CField::GetName(void)    { return StdString("field"); }
409   StdString CField::GetDefName(void) { return CField::GetName(); }
410   ENodeType CField::GetType(void)    { return eField; }
411
412   //----------------------------------------------------------------
413
414   CGrid* CField::getRelGrid(void) const
415   {
416      return this->grid;
417   }
418
419   //----------------------------------------------------------------
420
421   CFile* CField::getRelFile(void) const
422   {
423      return this->file;
424   }
425
426   StdSize CField::getNStep(void) const
427   {
428      return this->nstep;
429   }
430
431   void CField::incrementNStep(void)
432   {
433      this->nstep++;
434   }
435
436   void CField::resetNStep(void)
437   {
438      this->nstep = 0;
439   }
440
441   //----------------------------------------------------------------
442
443   const CDuration& CField::getFreqOperation(void) const
444   {
445      return this->freq_operation;
446   }
447
448   //----------------------------------------------------------------
449
450   const CDuration& CField::getFreqWrite(void) const
451   {
452      return this->freq_write;
453   }
454
455   //----------------------------------------------------------------
456
457   boost::shared_ptr<func::CFunctor> CField::getFieldOperation(void) const
458   {
459      return this->foperation;
460   }
461
462   bool CField::isActive(void) const
463   {
464      return !this->refObject.empty();
465   }
466
467   //----------------------------------------------------------------
468
469   CArray<double, 1> CField::getData(void) const
470   {
471      return(this->data);
472   }
473
474   //----------------------------------------------------------------
475
476   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
477   {
478      return(this->last_Write);
479   }
480
481   //----------------------------------------------------------------
482
483   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
484   {
485      return(this->last_operation);
486   }
487
488   //----------------------------------------------------------------
489
490//   void CField::processEnabledField(void)
491//   {
492//      if (!processed)
493//      {
494//        processed = true;
495//        solveRefInheritance(true);
496//        solveBaseReference();
497//        solveOperation();
498//        solveGridReference();
499//
500//        if (hasDirectFieldReference()) baseRefObject->processEnabledField();
501//        buildExpression();
502//        active = true;
503//      }
504//    }
505
506   void CField::solveAllReferenceEnabledField(bool doSending2Sever)
507   {
508     CContext* context = CContext::getCurrent();
509     if (!areAllReferenceSolved)
510     {
511        areAllReferenceSolved = true;
512        if (context->hasClient)
513        {
514          solveRefInheritance(true);
515          solveBaseReference();
516        }
517
518        solveOperation();
519        solveGridReference();
520     }
521     solveGridDomainAxisRef(doSending2Sever);
522     solveCheckMaskIndex(doSending2Sever);
523   }
524
525   std::map<int, StdSize> CField::getGridDataSize()
526   {
527     return grid->getConnectedServerDataSize();
528   }
529
530   void CField::buildAllExpressionEnabledField()
531   {
532     if (!areAllReferenceSolved) solveAllReferenceEnabledField(true);
533     if (!areAllExpressionBuilt)
534     {
535       areAllExpressionBuilt = true;
536//       solveCheckMaskIndex(true);
537//       solveCheckMaskIndex();
538       if (hasDirectFieldReference()) baseRefObject->buildAllExpressionEnabledField();
539       buildExpression();
540       active = true;
541     }
542   }
543
544   //----------------------------------------------------------------
545
546   void  CField::solveOperation(void)
547   {
548      using namespace func;
549
550      if (!hasOutputFile && !hasFieldOut) return;
551
552      StdString id;
553      if (hasId()) id = getId();
554      else if (!name.isEmpty()) id = name;
555      else if (hasDirectFieldReference()) id = baseRefObject->getId();
556
557      CContext* context = CContext::getCurrent();
558
559      if (freq_op.isEmpty()) freq_op.setValue(TimeStep);
560
561      if (operation.isEmpty())
562      {
563         ERROR("CField::solveOperation(void)",
564               << "[ id = " << id << "]"
565               << "Impossible to define an operation for this field !");
566      }
567
568      if (freq_offset.isEmpty())
569        freq_offset.setValue(NoneDu);
570
571//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
572      if (context->hasServer)
573      {
574         if (hasOutputFile)
575         {
576           this->freq_operation_srv = this->file->output_freq.getValue();
577           this->freq_write_srv = this->file->output_freq.getValue();
578         }
579         this->lastlast_Write_srv = boost::shared_ptr<CDate>
580                        (new CDate(context->getCalendar()->getInitDate()));
581         this->last_Write_srv     = boost::shared_ptr<CDate>
582                        (new CDate(context->getCalendar()->getInitDate()));
583         this->last_operation_srv = boost::shared_ptr<CDate>
584                        (new CDate(context->getCalendar()->getInitDate()));
585//         this->foperation_srv     =
586//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
587
588         if (hasOutputFile)
589         {
590           const CDuration toffset = this->freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
591           *this->last_operation_srv   = *this->last_operation_srv - toffset;
592         }
593      }
594
595//      if (context->hasClient)
596//      {
597         this->freq_operation = freq_op.getValue();
598         if (hasOutputFile) this->freq_write = this->file->output_freq.getValue();
599         if (hasFieldOut)
600         {
601           this->freq_write = this->fieldOut->freq_op.getValue();
602         }
603         this->last_Write     = boost::shared_ptr<CDate>
604                        (new CDate(context->getCalendar()->getInitDate()));
605         this->last_operation = boost::shared_ptr<CDate>
606                        (new CDate(context->getCalendar()->getInitDate()));
607
608         const CDuration toffset = this->freq_operation - freq_offset.getValue() - context->getCalendar()->getTimeStep();
609         *this->last_operation   = *this->last_operation - toffset;
610
611         lastDataRequestedFromServer.setRelCalendar(*context->getCalendar());
612
613        if (operation.get() == "once") isOnceOperation = true;
614        else isOnceOperation = false;
615        isFirstOperation = true;
616
617#define DECLARE_FUNCTOR(MType, mtype) \
618   if (operation.getValue().compare(#mtype) == 0) \
619   { \
620      if (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true) \
621      { \
622        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data,default_value)); \
623        this->foperation = foperation_; \
624      } \
625      else \
626      { \
627        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
628        this->foperation = foperation_; \
629      } \
630      return; \
631   }
632
633#include "functor_type.conf"
634
635         ERROR("CField::solveOperation(void)",
636               << "[ operation = " << operation.getValue() << "]"
637               << "The operation is not defined !");
638//      }
639   }
640
641   //----------------------------------------------------------------
642/*
643   void CField::fromBinary(StdIStream& is)
644   {
645      SuperClass::fromBinary(is);
646#define CLEAR_ATT(name_)\
647      SuperClassAttribute::operator[](#name_)->reset()
648
649         CLEAR_ATT(domain_ref);
650         CLEAR_ATT(axis_ref);
651#undef CLEAR_ATT
652
653   }
654*/
655   //----------------------------------------------------------------
656
657   void CField::solveGridReference(void)
658   {
659      CDomain* domain;
660      CAxis* axis;
661      std::vector<CDomain*> vecDom;
662      std::vector<CAxis*> vecAxis;
663      std::vector<std::string> domList, axisList;
664
665      if (!domain_ref.isEmpty())
666      {
667         if (CDomain::has(domain_ref.getValue()))
668         {
669           domain = CDomain::get(domain_ref.getValue());
670           vecDom.push_back(domain);
671         }
672         else
673            ERROR("CField::solveGridReference(void)",
674                  << "Reference to the domain \'"
675                  << domain_ref.getValue() << "\' is wrong");
676      }
677
678      if (!axis_ref.isEmpty())
679      {
680         if (CAxis::has(axis_ref.getValue()))
681         {
682           axis = CAxis::get(axis_ref.getValue());
683           vecAxis.push_back(axis);
684         }
685         else
686            ERROR("CField::solveGridReference(void)",
687                  << "Reference to the axis \'"
688                  << axis_ref.getValue() <<"\' is wrong");
689      }
690
691      if (!grid_ref.isEmpty())
692      {
693         if (CGrid::has(grid_ref.getValue()))
694         {
695           this->grid = CGrid::get(grid_ref.getValue());
696           domList = grid->getDomainList();
697           axisList = grid->getAxisList();
698           if (domList.empty() && axisList.empty() && (!(this->grid->scalar_grid.getValue())))
699           {
700             this->grid = CGrid::createGrid(vecDom, vecAxis);
701           }
702         }
703         else
704            ERROR("CField::solveGridReference(void)",
705                  << "Reference to the grid \'"
706                  << grid_ref.getValue() << "\' is wrong");
707      }
708      else
709      {
710         this->grid = CGrid::createGrid(vecDom, vecAxis);
711      }
712
713      if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty())
714      {
715            ERROR("CField::solveGridReference(void)",
716                  << "At least one dimension must be defined for this field.");
717      }
718   }
719
720   void CField::solveGridDomainAxisRef(bool checkAtt)
721   {
722     grid->solveDomainAxisRef(checkAtt);
723   }
724
725   void CField::solveCheckMaskIndex(bool doSendingIndex)
726   {
727     grid->checkMaskIndex(doSendingIndex);
728   }
729
730   ///-------------------------------------------------------------------
731
732   template <>
733   void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
734   {
735      if (this->group_ref.isEmpty()) return;
736      StdString gref = this->group_ref.getValue();
737
738      if (!CFieldGroup::has(gref))
739         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
740               << "[ gref = " << gref << "]"
741               << " invalid group name !");
742
743      CFieldGroup* group = CFieldGroup::get(gref);
744      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
745
746      std::vector<CField*> allChildren  = group->getAllChildren();
747      std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end();
748
749      for (; it != end; it++)
750      {
751         CField* child = *it;
752         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId());
753
754      }
755   }
756
757   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
758   {
759     map<int, CArray<double,1>* >::iterator it;
760     for (it = data_srv.begin(); it != data_srv.end(); it++) *it->second = (*it->second - addOffset) / scaleFactor;
761   }
762
763   void CField::outputField(CArray<double,3>& fieldOut)
764   {
765      map<int, CArray<double,1>* >::iterator it;
766      for (it = data_srv.begin(); it != data_srv.end(); it++)
767      {
768        grid->outputField(it->first,*it->second, fieldOut.dataFirst());
769      }
770   }
771
772   void CField::outputField(CArray<double,2>& fieldOut)
773   {
774      map<int, CArray<double,1>* >::iterator it;
775      for(it=data_srv.begin();it!=data_srv.end();it++)
776      {
777         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
778      }
779   }
780
781   void CField::outputField(CArray<double,1>& fieldOut)
782   {
783      map<int, CArray<double,1>* >::iterator it;
784
785      for (it = data_srv.begin(); it != data_srv.end(); it++)
786      {
787         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
788      }
789   }
790
791   ///-------------------------------------------------------------------
792
793   void CField::parse(xml::CXMLNode& node)
794   {
795      SuperClass::parse(node);
796      if (!node.getContent(this->content))
797      {
798        if (node.goToChildElement())
799        {
800          do
801          {
802            if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node);
803          } while (node.goToNextElement());
804          node.goToParentElement();
805        }
806      }
807    }
808
809  CArray<double,1>* CField::getInstantData(void)
810  {
811    if (!hasInstantData)
812    {
813      instantData.resize(grid->storeIndex_client.numElements());
814      hasInstantData = true;
815    }
816    return &instantData;
817  }
818
819  void CField::addDependency(CField* field, int slotId)
820  {
821    fieldDependency.push_back(pair<CField*,int>(field,slotId));
822  }
823
824  void CField::buildExpression(void)
825  {
826    if (content.size() > 0)
827    {
828      CSimpleNodeExpr* simpleExpr = parseExpr(content+'\0');
829      expression = CFieldNode::newNode(simpleExpr);
830      delete simpleExpr;
831      set<string> instantFieldIds;
832      map<string,CField*> associatedInstantFieldIds;
833      expression->getInstantFieldIds(instantFieldIds);
834      for (set<string>::iterator it = instantFieldIds.begin(); it != instantFieldIds.end(); ++it)
835      {
836        if (*it != "this")
837        {
838          if (CField::has(*it))
839          {
840            CField* field = CField::get(*it);
841//            field->processEnabledField();
842            field->buildAllExpressionEnabledField();
843            associatedInstantFieldIds[*it] = field;
844          }
845          else  ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
846        }
847      }
848
849      set<string> averageFieldIds;
850      map<string,CField*> associatedAverageFieldIds;
851
852      expression->getAverageFieldIds(averageFieldIds);
853      for (set<string>::iterator it = averageFieldIds.begin(); it != averageFieldIds.end(); ++it)
854      {
855        if (CField::has(*it))
856        {
857           CFieldGroup* root = CFieldGroup::get("field_definition");
858           CField* averageField = root->createChild();
859           CField* instantField = root->createChild();
860           averageField->field_ref = *it;
861           averageField->hasFieldOut = true;
862           averageField->fieldOut = instantField;
863           instantField->freq_op = freq_op;
864//           averageField-> processEnabledField();
865           averageField->buildAllExpressionEnabledField();
866           instantField->SuperClassAttribute::setAttributes(averageField, true);
867           instantField->field_ref.reset();
868           instantField->operation.reset();
869
870//           instantField-> processEnabledField();
871           instantField->buildAllExpressionEnabledField();
872           associatedAverageFieldIds[*it] = instantField;
873        }
874        else ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
875      }
876
877      expression->reduce(this,associatedInstantFieldIds,associatedAverageFieldIds);
878
879      slots.resize(instantFieldIds.size() + averageFieldIds.size());
880      resetSlots();
881      int slotId = 0;
882      set<CField*> fields;
883      expression->getFields(fields);
884      for (set<CField*>::iterator it = fields.begin(); it != fields.end(); ++it, ++slotId) (*it)->addDependency(this,slotId);
885      hasExpression = true;
886    }
887  }
888
889  void CField::resetSlots(void)
890  {
891    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) *it = false;
892  }
893
894  bool CField::slotsFull(void)
895  {
896    bool ret = true;
897    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) ret &= *it;
898    return ret;
899  }
900
901  void CField::setSlot(int slotId)
902  {
903    CContext* context = CContext::getCurrent();
904    const CDate& currDate = context->getCalendar()->getCurrentDate();
905    if (slotUpdateDate == NULL || currDate != *slotUpdateDate)
906    {
907      resetSlots();
908      if (slotUpdateDate == NULL) slotUpdateDate = new CDate(currDate);
909      else *slotUpdateDate = currDate;
910    }
911    slots[slotId] = true;
912    if (slotsFull())
913    {
914      CArray<double,1> expr(expression->compute());
915
916      if (hasInstantData)
917      {
918        instantData = expr;
919        for (list< pair<CField *,int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it)
920          if (it->first != this) it->first->setSlot(it->second);
921      }
922
923      if (hasOutputFile) updateDataFromExpression(expr);
924
925      const std::vector<CField*>& refField = getAllReference();
926      for (std::vector<CField*>::const_iterator it = refField.begin(); it != refField.end(); it++)
927      {
928        if (!(*it)->hasExpression)
929          (*it)->setDataFromExpression(expr);
930      }
931    }
932  }
933
934   /*!
935     This function retrieves Id of corresponding domain_ref and axis_ref (if any)
936   of a field. In some cases, only domain exists but axis doesn't
937   \return pair of Domain and Axis id
938   */
939   const std::pair<StdString,StdString>& CField::getRefDomainAxisIds()
940   {
941     CGrid* cgPtr = getRelGrid();
942     if (NULL != cgPtr)
943     {
944       std::vector<StdString>::iterator it;
945       if (!domain_ref.isEmpty())
946       {
947         std::vector<StdString> domainList = cgPtr->getDomainList();
948         it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue());
949         if (domainList.end() != it) domAxisIds_.first = *it;
950       }
951
952       if (!axis_ref.isEmpty())
953       {
954         std::vector<StdString> axisList = cgPtr->getAxisList();
955         it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue());
956         if (axisList.end() != it) domAxisIds_.second = *it;
957       }
958     }
959     return (domAxisIds_);
960   }
961
962   CVariable* CField::addVariable(const string& id)
963   {
964     return vVariableGroup->createChild(id);
965   }
966
967   CVariableGroup* CField::addVariableGroup(const string& id)
968   {
969     return vVariableGroup->createChildGroup(id);
970   }
971
972   void CField::sendAddAllVariables()
973   {
974     if (!getAllVariables().empty())
975     {
976       // Firstly, it's necessary to add virtual variable group
977       sendAddVariableGroup(getVirtualVariableGroup()->getId());
978
979       // Okie, now we can add to this variable group
980       std::vector<CVariable*> allVar = getAllVariables();
981       std::vector<CVariable*>::const_iterator it = allVar.begin();
982       std::vector<CVariable*>::const_iterator itE = allVar.end();
983
984       for (; it != itE; ++it)
985       {
986         this->sendAddVariable((*it)->getId());
987         (*it)->sendAllAttributesToServer();
988         (*it)->sendValue();
989       }
990     }
991   }
992
993   void CField::sendAddVariable(const string& id)
994   {
995    CContext* context = CContext::getCurrent();
996
997    if (!context->hasServer)
998    {
999       CContextClient* client = context->client;
1000
1001       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
1002       if (client->isServerLeader())
1003       {
1004         CMessage msg;
1005         msg << this->getId();
1006         msg << id;
1007         const std::list<int>& ranks = client->getRanksServerLeader();
1008         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1009           event.push(*itRank,1,msg);
1010         client->sendEvent(event);
1011       }
1012       else client->sendEvent(event);
1013    }
1014   }
1015
1016   void CField::sendAddVariableGroup(const string& id)
1017   {
1018    CContext* context = CContext::getCurrent();
1019    if (!context->hasServer)
1020    {
1021       CContextClient* client = context->client;
1022
1023       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP);
1024       if (client->isServerLeader())
1025       {
1026         CMessage msg;
1027         msg << this->getId();
1028         msg << id;
1029         const std::list<int>& ranks = client->getRanksServerLeader();
1030         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1031           event.push(*itRank,1,msg);
1032         client->sendEvent(event);
1033       }
1034       else client->sendEvent(event);
1035    }
1036   }
1037
1038   void CField::recvAddVariable(CEventServer& event)
1039   {
1040
1041      CBufferIn* buffer = event.subEvents.begin()->buffer;
1042      string id;
1043      *buffer >> id;
1044      get(id)->recvAddVariable(*buffer);
1045   }
1046
1047   void CField::recvAddVariable(CBufferIn& buffer)
1048   {
1049      string id;
1050      buffer >> id;
1051      addVariable(id);
1052   }
1053
1054   void CField::recvAddVariableGroup(CEventServer& event)
1055   {
1056
1057      CBufferIn* buffer = event.subEvents.begin()->buffer;
1058      string id;
1059      *buffer >> id;
1060      get(id)->recvAddVariableGroup(*buffer);
1061   }
1062
1063   void CField::recvAddVariableGroup(CBufferIn& buffer)
1064   {
1065      string id;
1066      buffer >> id;
1067      addVariableGroup(id);
1068   }
1069
1070   DEFINE_REF_FUNC(Field,field)
1071
1072//  void CField::addReference(CField* field)
1073//  {
1074//    refObject.push_back(field);
1075//  }
1076//
1077//   //----------------------------------------------------------------
1078//
1079//   bool CField::hasDirectFieldReference(void) const
1080//   {
1081//     return !this->field_ref.isEmpty();
1082//   }
1083//
1084//   //----------------------------------------------------------------
1085//
1086//   const StdString& CField::getBaseFieldId(void) const
1087//   {
1088//      return this->getBaseFieldReference()->getId();
1089//   }
1090//
1091//   //----------------------------------------------------------------
1092//
1093//   /*!
1094//   \brief Get pointer to direct field to which the current field refers.
1095//   */
1096//   CField* CField::getDirectFieldReference(void) const
1097//   {
1098//      if (this->field_ref.isEmpty())
1099//         return this->getBaseFieldReference();
1100//
1101//      if (!CField::has(this->field_ref.getValue()))
1102//         ERROR("CField::getDirectFieldReference(void)",
1103//               << "[ ref_name = " << this->field_ref.getValue() << "]"
1104//               << " invalid field name !");
1105//
1106//      return CField::get(this->field_ref.getValue());
1107//   }
1108//
1109//   //----------------------------------------------------------------
1110//
1111//   CField* CField::getBaseFieldReference(void) const
1112//   {
1113//      return baseRefObject;
1114//   }
1115//
1116//   //----------------------------------------------------------------
1117//
1118//   const std::vector<CField*>& CField::getAllReference(void) const
1119//   {
1120//      return refObject;
1121//   }
1122//
1123//   /*!
1124//   \brief Searching for all reference of a field
1125//   If a field refers to (an)other field(s), we will search for all its referenced parents.
1126//   Moreover, if any father, direct or indirect (e.g: two levels up), has non-empty attributes,
1127//   all its attributes will be added to the current field
1128//   \param [in] apply Flag to specify whether current field uses attributes of its father
1129//               in case the attribute is empty (true) or its attributes are replaced by ones of its father (false)
1130//   */
1131//   void CField::solveRefInheritance(bool apply)
1132//   {
1133//      std::set<CField *> sset;
1134//      CField* refer_sptr;
1135//      CField* refer_ptr = this;
1136//
1137//      while (refer_ptr->hasDirectFieldReference())
1138//      {
1139//         refer_sptr = refer_ptr->getDirectFieldReference();
1140//         refer_ptr  = refer_sptr;
1141//
1142//         if(sset.end() != sset.find(refer_ptr))
1143//         {
1144//            DEBUG (<< "Circular dependency stopped for field object on "
1145//                   << "\"" + refer_ptr->getId() + "\" !");
1146//            break;
1147//         }
1148//
1149//         SuperClassAttribute::setAttributes(refer_ptr, apply);
1150//         sset.insert(refer_ptr);
1151//      }
1152//   }
1153//
1154//   /*!
1155//   \brief Only on SERVER side. Remove all field_ref from current field
1156//   On creating a new field on server side, redundant "field_ref" is still kept in the attribute list
1157//   of the current field. This function removes this from current field
1158//   */
1159//   void CField::removeRefInheritance()
1160//   {
1161//     if (this->field_ref.isEmpty()) return;
1162//     this->clearAttribute("field_ref");
1163//   }
1164//
1165//   void CField::solveBaseReference(void)
1166//   {
1167//      std::set<CField *> sset;
1168//      CField* refer_sptr;
1169//      CField* refer_ptr = this;
1170//
1171//      if (this->hasDirectFieldReference())  baseRefObject = getDirectFieldReference();
1172//      else  baseRefObject = CField::get(this);
1173//
1174//      while (refer_ptr->hasDirectFieldReference())
1175//      {
1176//         refer_sptr = refer_ptr->getDirectFieldReference();
1177//         refer_ptr  = refer_sptr;
1178//
1179//         if(sset.end() != sset.find(refer_ptr))
1180//         {
1181//            DEBUG (<< "Circular dependency stopped for field object on "
1182//                   << "\"" + refer_ptr->getId() + "\" !");
1183//            break;
1184//         }
1185//
1186//         sset.insert(refer_ptr);
1187//      }
1188//
1189//      if (hasDirectFieldReference()) baseRefObject->addReference(this);
1190//   }
1191} // namespace xios
Note: See TracBrowser for help on using the repository browser.