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

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