source: XIOS/branchs/xios-1.0/src/node/field.cpp @ 562

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

Fix incorrect output values when using a field_ref or the @ operator on a field computed from an operation.

The computed values were never transmitted from the source field to the destination field.

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