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

Last change on this file since 598 was 598, checked in by rlacroix, 10 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.