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

Last change on this file since 595 was 595, checked in by rlacroix, 10 years ago

Allow using more servers than clients.

This will be useful later when implementing server to client communications.

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