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

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

Add a source filter and two terminal filters.

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