source: XIOS/dev/dev_olga/src/node/field.cpp @ 1025

Last change on this file since 1025 was 1025, checked in by mhnguyen, 7 years ago

Merging working version of coupler

+) Add some changes of domain and axis: Retransfer the atttributes in a generic ways for each level of client (or server)
+) Remove some spoiled files from the previous commits

Test
+) No test

  • 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: 53.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 "xios_spl.hpp"
11#include "type.hpp"
12#include "timer.hpp"
13#include "context_client.hpp"
14#include "context_server.hpp"
15#include <set>
16#include "garbage_collector.hpp"
17#include "source_filter.hpp"
18#include "store_filter.hpp"
19#include "file_writer_filter.hpp"
20#include "pass_through_filter.hpp"
21#include "filter_expr_node.hpp"
22#include "lex_parser.hpp"
23#include "temporal_filter.hpp"
24#include "spatial_transform_filter.hpp"
25#include "file_server_writer_filter.hpp"
26
27namespace xios{
28
29   /// ////////////////////// Définitions ////////////////////// ///
30
31   CField::CField(void)
32      : CObjectTemplate<CField>(), CFieldAttributes()
33      , grid(), file()
34      , written(false)
35      , nstep(0), nstepMax(0)
36      , hasOutputFile(false)
37      , domAxisScalarIds_(vector<StdString>(3,"")), areAllReferenceSolved(false), isReferenceSolved(false)
38      , useCompressedOutput(false)
39      , wasDataAlreadyReceivedFromServer(false)
40   { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); }
41
42   CField::CField(const StdString& id)
43      : CObjectTemplate<CField>(id), CFieldAttributes()
44      , grid(), file()
45      , written(false)
46      , nstep(0), nstepMax(0)
47      , hasOutputFile(false)
48      , domAxisScalarIds_(vector<StdString>(3,"")), areAllReferenceSolved(false), isReferenceSolved(false)
49      , useCompressedOutput(false)
50      , wasDataAlreadyReceivedFromServer(false)
51   { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); }
52
53   CField::~CField(void)
54   {}
55
56  //----------------------------------------------------------------
57
58   void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
59   {
60      this->vVariableGroup = newVVariableGroup;
61   }
62
63   CVariableGroup* CField::getVirtualVariableGroup(void) const
64   {
65      return this->vVariableGroup;
66   }
67
68   std::vector<CVariable*> CField::getAllVariables(void) const
69   {
70      return this->vVariableGroup->getAllChildren();
71   }
72
73   void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent)
74   {
75      SuperClassAttribute::setAttributes(parent, apply);
76      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
77   }
78
79  //----------------------------------------------------------------
80
81  bool CField::dispatchEvent(CEventServer& event)
82  {
83    if (SuperClass::dispatchEvent(event)) return true;
84    else
85    {
86      switch(event.type)
87      {
88        case EVENT_ID_UPDATE_DATA :
89          recvUpdateData(event);
90          return true;
91          break;
92
93        case EVENT_ID_READ_DATA :
94          recvReadDataRequest(event);
95          return true;
96          break;
97
98        case EVENT_ID_READ_DATA_READY :
99          recvReadDataReady(event);
100          return true;
101          break;
102
103        case EVENT_ID_ADD_VARIABLE :
104          recvAddVariable(event);
105          return true;
106          break;
107
108        case EVENT_ID_ADD_VARIABLE_GROUP :
109          recvAddVariableGroup(event);
110          return true;
111          break;
112
113        default :
114          ERROR("bool CField::dispatchEvent(CEventServer& event)", << "Unknown Event");
115          return false;
116      }
117    }
118  }
119
120  void CField::sendUpdateData(const CArray<double,1>& data)
121  {
122    CTimer::get("XIOS Send Data").resume();
123
124    CContext* context = CContext::getCurrent();
125//    CContextClient* client = context->client;
126    int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
127    for (int i = 0; i < nbSrvPools; ++i)
128    {
129      CContextClient* client = (!context->hasServer) ? context->client : context->clientPrimServer[i];
130
131      CEventClient event(getType(), EVENT_ID_UPDATE_DATA);
132
133      map<int, CArray<int,1> >::iterator it;
134      list<CMessage> list_msg;
135      list<CArray<double,1> > list_data;
136
137      if (!grid->doGridHaveDataDistributed())
138      {
139         if (client->isServerLeader())
140         {
141            for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
142            {
143              int rank = it->first;
144              CArray<int,1>& index = it->second;
145
146              list_msg.push_back(CMessage());
147              list_data.push_back(CArray<double,1>(index.numElements()));
148
149              CArray<double,1>& data_tmp = list_data.back();
150              for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
151
152              list_msg.back() << getId() << data_tmp;
153              event.push(rank, 1, list_msg.back());
154            }
155            client->sendEvent(event);
156         }
157         else client->sendEvent(event);
158      }
159      else
160      {
161        for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
162        {
163          int rank = it->first;
164          CArray<int,1>& index = it->second;
165
166          list_msg.push_back(CMessage());
167          list_data.push_back(CArray<double,1>(index.numElements()));
168
169          CArray<double,1>& data_tmp = list_data.back();
170          for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
171
172          list_msg.back() << getId() << data_tmp;
173          event.push(rank, grid->nbSenders[rank], list_msg.back());
174        }
175        client->sendEvent(event);
176      }
177    }
178
179    CTimer::get("XIOS Send Data").suspend();
180  }
181
182  void CField::sendUpdateData(const CArray<double,1>& data, CContextClient* client)
183  {
184    CTimer::get("XIOS Send Data").resume();
185
186    CEventClient event(getType(), EVENT_ID_UPDATE_DATA);
187
188    map<int, CArray<int,1> >::iterator it;
189    list<CMessage> list_msg;
190    list<CArray<double,1> > list_data;
191
192    if (!grid->doGridHaveDataDistributed())
193    {
194       if (client->isServerLeader())
195       {
196          for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
197          {
198            int rank = it->first;
199            CArray<int,1>& index = it->second;
200
201            list_msg.push_back(CMessage());
202            list_data.push_back(CArray<double,1>(index.numElements()));
203
204            CArray<double,1>& data_tmp = list_data.back();
205            for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
206
207            list_msg.back() << getId() << data_tmp;
208            event.push(rank, 1, list_msg.back());
209          }
210          client->sendEvent(event);
211       }
212       else client->sendEvent(event);
213    }
214    else
215    {
216      for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
217      {
218        int rank = it->first;
219        CArray<int,1>& index = it->second;
220
221        list_msg.push_back(CMessage());
222        list_data.push_back(CArray<double,1>(index.numElements()));
223
224        CArray<double,1>& data_tmp = list_data.back();
225        for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
226
227        list_msg.back() << getId() << data_tmp;
228        event.push(rank, grid->nbSenders[rank], list_msg.back());
229      }
230      client->sendEvent(event);
231    }
232    CTimer::get("XIOS Send Data").suspend();
233  }
234
235  void CField::recvUpdateData(CEventServer& event)
236  {
237    std::map<int,CBufferIn*> rankBuffers;
238
239    list<CEventServer::SSubEvent>::iterator it;
240    string fieldId;
241
242    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
243    {
244      int rank = it->rank;
245      CBufferIn* buffer = it->buffer;
246      *buffer >> fieldId;
247      rankBuffers[rank] = buffer;
248    }
249    get(fieldId)->recvUpdateData(rankBuffers);
250  }
251
252  void  CField::recvUpdateData(std::map<int,CBufferIn*>& rankBuffers)
253  {
254    CContext* context = CContext::getCurrent();
255
256    size_t sizeData = 0;
257    if (0 == recvDataSrv.numElements())
258    {     
259      for (map<int, CArray<size_t, 1> >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
260      {
261        sizeData += it->second.numElements();
262      }
263
264      // Gather all data from different clients
265      recvDataSrv.resize(sizeData);
266      recvFoperationSrv = boost::shared_ptr<func::CFunctor>(new func::CInstant(recvDataSrv));
267    }
268
269    CArray<double,1> recv_data_tmp(recvDataSrv.numElements());
270    sizeData = 0;
271    const CDate& currDate = context->getCalendar()->getCurrentDate();
272    const CDate opeDate      = last_operation_srv +freq_op + freq_operation_srv - freq_op;
273
274    if (opeDate <= currDate)
275    {
276      for (map<int, CArray<size_t, 1> >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
277      {       
278        CArray<double,1> tmp;       
279        *(rankBuffers[it->first]) >> tmp;
280        recv_data_tmp(Range(sizeData,sizeData+it->second.numElements()-1)) = tmp; 
281        sizeData += it->second.numElements();     
282      }
283    }
284
285    this->setData(recv_data_tmp);
286  }
287
288  void CField::writeUpdateData(const CArray<double,1>& data)
289  {
290    CContext* context = CContext::getCurrent();
291
292    const CDate& currDate = context->getCalendar()->getCurrentDate();
293    const CDate opeDate      = last_operation_srv +freq_op + freq_operation_srv - freq_op;
294    const CDate writeDate    = last_Write_srv     + freq_write_srv;
295
296    if (opeDate <= currDate)
297    {
298      (*recvFoperationSrv)(data);
299      last_operation_srv = currDate;
300//        sendUpdateData(fieldData);
301        // Redirecting data to the correct secondary server
302        //int fileIdx = std::find(context->enabledFiles.begin(), context->enabledFiles.end(), this->file) - context->enabledFiles.begin();
303        //int srvId = fileIdx % context->clientPrimServer.size();
304        //sendUpdateData(fieldData, context->clientPrimServer[srvId]);
305    }
306
307    if (writeDate < (currDate + freq_operation_srv))
308    {
309      recvFoperationSrv->final();
310      last_Write_srv = writeDate;
311      writeField();
312      lastlast_Write_srv = last_Write_srv;
313    }
314  }
315 
316//   void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
317//   {
318//     CContext* context = CContext::getCurrent();
319
320//     if (data_srv.empty())
321//     {
322//       for (map<int, CArray<size_t, 1> >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
323//       {
324//         int rank = it->first;
325//         data_srv.insert(std::make_pair(rank, CArray<double,1>(it->second.numElements())));
326//         foperation_srv.insert(pair<int,boost::shared_ptr<func::CFunctor> >(rank,boost::shared_ptr<func::CFunctor>(new func::CInstant(data_srv[rank]))));
327//       }
328//     }
329
330//     const CDate& currDate = context->getCalendar()->getCurrentDate();
331//     const CDate opeDate      = last_operation_srv +freq_op + freq_operation_srv - freq_op;
332//     const CDate writeDate    = last_Write_srv     + freq_write_srv;
333
334//     if (opeDate <= currDate)
335//     {
336//       for (int n = 0; n < ranks.size(); n++)
337//       {
338//         CArray<double,1> data_tmp;
339//         *buffers[n] >> data_tmp;
340//         (*foperation_srv[ranks[n]])(data_tmp);
341//       }
342//       last_operation_srv = currDate;
343//     }
344
345//     if (writeDate < (currDate + freq_operation_srv))
346//     {
347//       for (int n = 0; n < ranks.size(); n++)
348//       {
349//         this->foperation_srv[ranks[n]]->final();
350//       }
351
352//       last_Write_srv = writeDate;
353//     }
354
355//     if (context->hasClient && context->hasServer)
356//     {
357//       size_t writtenSize;
358// //      if (field->getUseCompressedOutput())
359// //        writtenSize = grid->getNumberWrittenIndexes();
360// //      else
361//         writtenSize = grid->getWrittenDataSize();
362
363//       CArray<double,1> fieldData(writtenSize);
364// //      if (!field->default_value.isEmpty()) fieldData = field->default_value;
365
366// //      if (field->getUseCompressedOutput())
367// //        field->outputCompressedField(fieldData);
368// //      else
369//         this->outputField(fieldData);
370//       sendUpdateData(fieldData);
371//     }
372//     if (!context->hasClient && context->hasServer)
373//     {
374//       writeField();
375//     }
376
377//     lastlast_Write_srv = last_Write_srv;
378
379//   }
380
381  void CField::writeField(void)
382  {
383    if (!getRelFile()->allDomainEmpty)
384    {
385      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
386      {
387        getRelFile()->checkFile();
388        this->incrementNStep();
389        getRelFile()->getDataOutput()->writeFieldData(CField::get(this));
390      }
391    }
392  }
393
394  void CField::sendReadDataRequest(const CDate& tsDataRequested)
395  {
396    CContext* context = CContext::getCurrent();
397    CContextClient* client = context->client;
398
399    lastDataRequestedFromServer = tsDataRequested;
400
401    CEventClient event(getType(), EVENT_ID_READ_DATA);
402    if (client->isServerLeader())
403    {
404      CMessage msg;
405      msg << getId();
406      const std::list<int>& ranks = client->getRanksServerLeader();
407      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
408        event.push(*itRank, 1, msg);
409      client->sendEvent(event);
410    }
411    else client->sendEvent(event);
412  }
413
414  /*!
415  Send request new data read from file if need be, that is the current data is out-of-date.
416  \return true if and only if some data was requested
417  */
418  bool CField::sendReadDataRequestIfNeeded(void)
419  {
420    const CDate& currentDate = CContext::getCurrent()->getCalendar()->getCurrentDate();
421
422    bool dataRequested = false;
423    while (currentDate >= lastDataRequestedFromServer)
424    {
425      info(20) << "currentDate : " << currentDate << endl ;
426      info(20) << "lastDataRequestedFromServer : " << lastDataRequestedFromServer << endl ;
427      info(20) << "file->output_freq.getValue() : " << file->output_freq.getValue() << endl ;
428      info(20) << "lastDataRequestedFromServer + file->output_freq.getValue() : " << lastDataRequestedFromServer + file->output_freq << endl ;
429
430      sendReadDataRequest(lastDataRequestedFromServer + file->output_freq);
431
432      dataRequested = true;
433    }
434    return dataRequested;
435  }
436
437  void CField::recvReadDataRequest(CEventServer& event)
438  {
439    CBufferIn* buffer = event.subEvents.begin()->buffer;
440    StdString fieldId;
441    *buffer >> fieldId;
442    get(fieldId)->recvReadDataRequest();
443  }
444
445  void CField::recvReadDataRequest(void)
446  {
447    CContext* context = CContext::getCurrent();
448    CContextClient* client = context->client;
449
450    CEventClient event(getType(), EVENT_ID_READ_DATA_READY);
451    std::list<CMessage> msgs;
452
453    bool hasData = readField();
454
455    map<int, CArray<double,1> >::iterator it;
456//    for (it = data_srv.begin(); it != data_srv.end(); it++)
457//    {
458//      msgs.push_back(CMessage());
459//      CMessage& msg = msgs.back();
460//      msg << getId();
461//      if (hasData)
462//        msg << getNStep() - 1 << it->second;
463//      else
464//        msg << int(-1);
465//      event.push(it->first, grid->nbSenders[it->first], msg);
466//    }
467//    client->sendEvent(event);
468    if (!grid->doGridHaveDataDistributed())
469    {
470       if (client->isServerLeader())
471       {
472          if (!data_srv.empty())
473          {
474            it = data_srv.begin();
475            const std::list<int>& ranks = client->getRanksServerLeader();
476            for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
477            {
478              msgs.push_back(CMessage());
479              CMessage& msg = msgs.back();
480              msg << getId();
481              if (hasData)
482                msg << getNStep() - 1 << it->second;
483              else
484                msg << int(-1);
485              event.push(*itRank, 1, msg);
486            }
487          }
488          client->sendEvent(event);
489       }
490       else
491       {
492          // if (!data_srv.empty())
493          // {
494          //   it = data_srv.begin();
495          //   const std::list<int>& ranks = client->getRanksServerNotLeader();
496          //   for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
497          //   {
498          //     msgs.push_back(CMessage());
499          //     CMessage& msg = msgs.back();
500          //     msg << getId();
501          //     if (hasData)
502          //       msg << getNStep() - 1 << it->second;
503          //     else
504          //       msg << int(-1);
505          //     event.push(*itRank, 1, msg);
506          //   }
507          // }
508          client->sendEvent(event);
509       }
510    }
511    else
512    {
513      for (it = data_srv.begin(); it != data_srv.end(); it++)
514      {
515        msgs.push_back(CMessage());
516        CMessage& msg = msgs.back();
517        msg << getId();
518        if (hasData)
519          msg << getNStep() - 1 << it->second;
520        else
521          msg << int(-1);
522        event.push(it->first, grid->nbSenders[it->first], msg);
523      }
524      client->sendEvent(event);
525    }
526  }
527
528  bool CField::readField(void)
529  {
530    if (!getRelFile()->allDomainEmpty)
531    {
532      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
533      {
534        if (data_srv.empty())
535        {
536          for (map<int, CArray<size_t, 1> >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
537            data_srv.insert(std::make_pair(it->first, CArray<double,1>(it->second.numElements())));
538        }
539
540        getRelFile()->checkFile();
541        if (!nstepMax)
542        {
543          nstepMax = getRelFile()->getDataInput()->getFieldNbRecords(CField::get(this));
544        }
545
546        this->incrementNStep();
547
548
549
550        if (getNStep() > nstepMax && (getRelFile()->cyclic.isEmpty() || !getRelFile()->cyclic) )
551          return false;
552
553        getRelFile()->getDataInput()->readFieldData(CField::get(this));
554      }
555    }
556
557    return true;
558  }
559
560  void CField::recvReadDataReady(CEventServer& event)
561  {
562    string fieldId;
563    vector<int> ranks;
564    vector<CBufferIn*> buffers;
565
566    list<CEventServer::SSubEvent>::iterator it;
567    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
568    {
569      ranks.push_back(it->rank);
570      CBufferIn* buffer = it->buffer;
571      *buffer >> fieldId;
572      buffers.push_back(buffer);
573    }
574    get(fieldId)->recvReadDataReady(ranks, buffers);
575  }
576
577  void CField::recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers)
578  {
579    CContext* context = CContext::getCurrent();
580    int record;
581    std::map<int, CArray<double,1> > data;
582
583    bool isEOF = false;
584
585    for (int i = 0; i < ranks.size(); i++)
586    {
587      int rank = ranks[i];
588      *buffers[i] >> record;
589      isEOF = (record == int(-1));
590
591      if (!isEOF)
592        *buffers[i] >> data[rank];
593      else
594        break;
595    }
596
597    if (wasDataAlreadyReceivedFromServer)
598      lastDataReceivedFromServer = lastDataReceivedFromServer + file->output_freq;
599    else
600    {
601      lastDataReceivedFromServer = context->getCalendar()->getInitDate();
602      wasDataAlreadyReceivedFromServer = true;
603    }
604
605    if (isEOF)
606      serverSourceFilter->signalEndOfStream(lastDataReceivedFromServer);
607    else
608      serverSourceFilter->streamDataFromServer(lastDataReceivedFromServer, data);
609  }
610
611   //----------------------------------------------------------------
612
613   void CField::setRelFile(CFile* _file)
614   {
615      this->file = _file;
616      hasOutputFile = true;
617   }
618
619   //----------------------------------------------------------------
620
621   StdString CField::GetName(void)    { return StdString("field"); }
622   StdString CField::GetDefName(void) { return CField::GetName(); }
623   ENodeType CField::GetType(void)    { return eField; }
624
625   //----------------------------------------------------------------
626
627   CGrid* CField::getRelGrid(void) const
628   {
629      return this->grid;
630   }
631
632   //----------------------------------------------------------------
633
634   CFile* CField::getRelFile(void) const
635   {
636      return this->file;
637   }
638
639   int CField::getNStep(void) const
640   {
641      return this->nstep;
642   }
643
644   func::CFunctor::ETimeType CField::getOperationTimeType() const
645   {
646     return operationTimeType;
647   }
648
649   //----------------------------------------------------------------
650
651   void CField::incrementNStep(void)
652   {
653      this->nstep++;
654   }
655
656   void CField::resetNStep(int nstep /*= 0*/)
657   {
658      this->nstep = nstep;
659   }
660
661   void CField::resetNStepMax(void)
662   {
663      this->nstepMax = 0;
664   }
665
666   //----------------------------------------------------------------
667
668   bool CField::isActive(void) const
669   {
670      return (instantDataFilter != NULL);
671   }
672
673   //----------------------------------------------------------------
674
675   bool CField::wasWritten() const
676   {
677     return written;
678   }
679
680   void CField::setWritten()
681   {
682     written = true;
683   }
684
685   //----------------------------------------------------------------
686
687   bool CField::getUseCompressedOutput() const
688   {
689     return useCompressedOutput;
690   }
691
692   void CField::setUseCompressedOutput()
693   {
694     useCompressedOutput = true;
695   }
696
697   //----------------------------------------------------------------
698
699   boost::shared_ptr<COutputPin> CField::getInstantDataFilter()
700   {
701     return instantDataFilter;
702   }
703
704   //----------------------------------------------------------------
705
706   /*!
707     Build up graph of grids which plays role of destination and source in grid transformation
708     This function should be called before \func solveGridReference()
709   */
710   void CField::buildGridTransformationGraph()
711   {
712     CContext* context = CContext::getCurrent();
713     if (context->hasClient && !context->hasServer)
714//     if (context->hasClient)
715     {
716       if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid)
717       {
718         grid->addTransGridSource(getDirectFieldReference()->grid);
719       }
720     }
721   }
722
723   /*!
724     Generate a new grid destination if there are more than one grid source pointing to a same grid destination
725   */
726   void CField::generateNewTransformationGridDest()
727   {
728     CContext* context = CContext::getCurrent();
729     if (context->hasClient && !context->hasServer)
730//     if (context->hasClient)
731     {
732       std::map<CGrid*,std::pair<bool,StdString> >& gridSrcMap = grid->getTransGridSource();
733       if (1 < gridSrcMap.size())
734       {
735         // Search for grid source
736         CGrid* gridSrc = grid;
737         CField* currField = this;
738         std::vector<CField*> hieraField;
739
740         while (currField->hasDirectFieldReference() && (gridSrc == grid))
741         {
742           hieraField.push_back(currField);
743           CField* tmp = currField->getDirectFieldReference();
744           currField = tmp;
745           gridSrc = currField->grid;
746         }
747
748         if (gridSrcMap.end() != gridSrcMap.find(gridSrc))
749         {
750           CGrid* gridTmp;
751           std::pair<bool,StdString> newGridDest = gridSrcMap[gridSrc];
752           if (newGridDest.first)
753           {
754             StdString newIdGridDest = newGridDest.second;
755             if (!CGrid::has(newIdGridDest))
756             {
757                ERROR("CGrid* CGrid::generateNewTransformationGridDest()",
758                  << " Something wrong happened! Grid whose id " << newIdGridDest
759                  << "should exist ");
760             }
761             gridTmp = CGrid::get(newIdGridDest);
762           }
763           else
764           {
765             StdString newIdGridDest = CGrid::generateId(gridSrc, grid);
766             gridTmp = CGrid::cloneGrid(newIdGridDest, grid);
767
768             (gridSrcMap[gridSrc]).first = true;
769             (gridSrcMap[gridSrc]).second = newIdGridDest;
770           }
771
772           // Update all descendants
773           for (std::vector<CField*>::iterator it = hieraField.begin(); it != hieraField.end(); ++it)
774           {
775             (*it)->grid = gridTmp;
776             (*it)->updateRef((*it)->grid);
777           }
778         }
779       }
780     }
781   }
782
783   void CField::updateRef(CGrid* grid)
784   {
785     if (!grid_ref.isEmpty()) grid_ref.setValue(grid->getId());
786     else
787     {
788       std::vector<CAxis*> axisTmp = grid->getAxis();
789       std::vector<CDomain*> domainTmp = grid->getDomains();
790       if ((1<axisTmp.size()) || (1<domainTmp.size()))
791         ERROR("void CField::updateRef(CGrid* grid)",
792           << "More than one domain or axis is available for domain_ref/axis_ref of field " << this->getId());
793
794       if ((!domain_ref.isEmpty()) && (domainTmp.empty()))
795         ERROR("void CField::updateRef(CGrid* grid)",
796           << "Incoherent between available domain and domain_ref of field " << this->getId());
797       if ((!axis_ref.isEmpty()) && (axisTmp.empty()))
798         ERROR("void CField::updateRef(CGrid* grid)",
799           << "Incoherent between available axis and axis_ref of field " << this->getId());
800
801       if (!domain_ref.isEmpty()) domain_ref.setValue(domainTmp[0]->getId());
802       if (!axis_ref.isEmpty()) axis_ref.setValue(axisTmp[0]->getId());
803     }
804   }
805   
806   void CField::solveAllEnabledFields()
807   {
808     CContext* context = CContext::getCurrent();
809     bool hasClient = context->hasClient;
810     bool hasServer = context->hasServer;
811
812     if (!isReferenceSolved)
813     {
814        isReferenceSolved = true;
815
816        if (hasClient && !hasServer)
817        {
818          solveRefInheritance(true);
819          if (hasDirectFieldReference()) getDirectFieldReference()->solveAllEnabledFields();
820        }
821
822        if (hasServer)
823          solveServerOperation();
824
825        solveGridReference();
826
827        if (hasClient && !hasServer)
828       {
829         solveGenerateGrid();
830         buildGridTransformationGraph();
831       }
832
833       solveGridDomainAxisRef(false);
834
835       if (hasClient && !hasServer)
836       {
837         solveTransformedGrid();
838       }
839
840       solveGridDomainAxisRef(false);
841     }
842   }
843
844   void CField::checkGridOfEnabledFields()
845   {
846      solveCheckMaskIndex(false);
847   }
848
849   void CField::sendGridOfEnabledFields()
850   {
851      solveGridDomainAxisRef(true);
852      solveCheckMaskIndex(true);
853   }
854
855
856    void CField::solveOnlyReferenceEnabledField(bool doSending2Server)
857   {
858     CContext* context = CContext::getCurrent();
859     if (!isReferenceSolved)
860     {
861        isReferenceSolved = true;
862
863        if (context->hasClient && !context->hasServer)
864//        if (context->hasClient)
865        {
866          solveRefInheritance(true);
867          if (hasDirectFieldReference()) getDirectFieldReference()->solveOnlyReferenceEnabledField(false);
868        }
869//        else if (context->hasServer)
870        if (context->hasServer)
871          solveServerOperation();
872
873        solveGridReference();
874
875        if (context->hasClient && !context->hasServer)
876//       if (context->hasClient)
877       {
878         solveGenerateGrid();
879         buildGridTransformationGraph();
880       }
881     }
882   }
883     
884   void CField::solveAllReferenceEnabledField(bool doSending2Server)
885   {
886     CContext* context = CContext::getCurrent();
887     solveOnlyReferenceEnabledField(doSending2Server);
888
889     if (!areAllReferenceSolved)
890     {
891        areAllReferenceSolved = true;
892
893       // if (context->hasClient)
894        if (context->hasClient && !context->hasServer)
895        {
896          solveRefInheritance(true);
897          if (hasDirectFieldReference()) getDirectFieldReference()->solveAllReferenceEnabledField(false);
898        }
899       else if (context->hasServer)
900        // if (context->hasServer && !context->hasClient)
901          solveServerOperation();
902
903        solveGridReference();
904     }
905
906     solveGridDomainAxisRef(doSending2Server);
907
908     if (context->hasClient && !context->hasServer)
909     {
910       solveTransformedGrid();
911     }
912
913     solveCheckMaskIndex(doSending2Server);
914   }
915
916   std::map<int, StdSize> CField::getGridAttributesBufferSize()
917   {
918     return grid->getAttributesBufferSize();
919   }
920
921   std::map<int, StdSize> CField::getGridDataBufferSize()
922   {
923     return grid->getDataBufferSize(getId());
924   }
925
926   //----------------------------------------------------------------
927
928   void CField::solveServerOperation(void)
929   {
930      CContext* context = CContext::getCurrent();
931
932      if (!context->hasServer || !hasOutputFile) return;
933
934      if (freq_op.isEmpty())
935        freq_op.setValue(TimeStep);
936
937      if (freq_offset.isEmpty())
938        freq_offset.setValue(NoneDu);
939
940      freq_operation_srv = file->output_freq.getValue();
941      freq_write_srv     = file->output_freq.getValue();
942
943      lastlast_Write_srv = context->getCalendar()->getInitDate();
944      last_Write_srv     = context->getCalendar()->getInitDate();
945      last_operation_srv = context->getCalendar()->getInitDate();
946
947      const CDuration toffset = freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
948      last_operation_srv     = last_operation_srv - toffset;
949
950      if (operation.isEmpty())
951        ERROR("void CField::solveServerOperation(void)",
952              << "An operation must be defined for field \"" << getId() << "\".");
953
954      boost::shared_ptr<func::CFunctor> functor;
955      CArray<double, 1> dummyData;
956
957#define DECLARE_FUNCTOR(MType, mtype) \
958      if (operation.getValue().compare(#mtype) == 0) \
959      { \
960        functor.reset(new func::C##MType(dummyData)); \
961      }
962
963#include "functor_type.conf"
964
965      if (!functor)
966        ERROR("void CField::solveServerOperation(void)",
967              << "\"" << operation << "\" is not a valid operation.");
968
969      operationTimeType = functor->timeType();
970   }
971
972   //----------------------------------------------------------------
973
974   /*!
975    * Constructs the graph filter for the field, enabling or not the data output.
976    * This method should not be called more than once with enableOutput equal to true.
977    *
978    * \param gc the garbage collector to use when building the filter graph
979    * \param enableOutput must be true when the field data is to be
980    *                     read by the client or/and written to a file
981    */
982   void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput)
983   {
984     // if (!areAllReferenceSolved) solveAllReferenceEnabledField(false);
985    if (!isReferenceSolved) solveAllEnabledFields();
986     CContext* context = CContext::getCurrent();
987     bool hasWriterServer = context->hasServer && !context->hasClient;
988     bool hasIntermediateServer = context->hasServer && context->hasClient;
989
990     if (hasWriterServer)
991     {
992        if (!instantDataFilter)
993          instantDataFilter = clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(grid));
994
995             // If the field data is to be read by the client or/and written to a file
996       if (enableOutput && !storeFilter && !fileWriterFilter)
997       {
998         if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write))
999         {
1000           fileServerWriterFilter = boost::shared_ptr<CFileServerWriterFilter>(new CFileServerWriterFilter(gc, this));
1001           instantDataFilter->connectOutput(fileServerWriterFilter, 0);
1002         }
1003       }
1004     }
1005     else if (hasIntermediateServer)
1006     {
1007       if (!instantDataFilter)
1008          instantDataFilter = clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(grid));
1009
1010             // If the field data is to be read by the client or/and written to a file
1011       if (enableOutput && !storeFilter && !fileWriterFilter)
1012       {
1013         if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write))
1014         {
1015           fileWriterFilter = boost::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this));
1016           instantDataFilter->connectOutput(fileWriterFilter, 0);
1017         }
1018       }
1019     }
1020     else
1021     {
1022       // Start by building a filter which can provide the field's instant data
1023       if (!instantDataFilter)
1024       {
1025         // Check if we have an expression to parse
1026       if (hasExpression())
1027         {
1028         boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0'));
1029         boost::shared_ptr<COutputPin> filter = expr->reduce(gc, *this);
1030
1031         // Check if a spatial transformation is needed
1032         if (!field_ref.isEmpty())
1033         {
1034           CGrid* gridRef = CField::get(field_ref)->grid;
1035
1036           if (grid && grid != gridRef && grid->hasTransform())
1037           {
1038             double defaultValue = !default_value.isEmpty() ? default_value : 0.0;
1039             std::pair<boost::shared_ptr<CFilter>, boost::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid, defaultValue);
1040
1041             filter->connectOutput(filters.first, 0);
1042             filter = filters.second;
1043           }
1044         }
1045
1046         instantDataFilter = filter;
1047         }
1048         // Check if we have a reference on another field
1049         else if (!field_ref.isEmpty())
1050           instantDataFilter = getFieldReference(gc);
1051         // Check if the data is to be read from a file
1052         else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read)
1053         instantDataFilter = serverSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid,
1054                                                                                                     freq_offset.isEmpty() ? NoneDu : freq_offset,
1055                                                                                                     true));
1056         else // The data might be passed from the model
1057         instantDataFilter = clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid));
1058       }
1059
1060       // If the field data is to be read by the client or/and written to a file
1061       if (enableOutput && !storeFilter && !fileWriterFilter)
1062       {
1063         if (!read_access.isEmpty() && read_access)
1064         {
1065           storeFilter = boost::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid));
1066           instantDataFilter->connectOutput(storeFilter, 0);
1067         }
1068
1069         if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write))
1070         {
1071           fileWriterFilter = boost::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this));
1072           getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0);
1073         }
1074       }
1075     }
1076   }
1077
1078
1079   /*!
1080    * Returns the filter needed to handle the field reference.
1081    * This method should only be called when building the filter graph corresponding to the field.
1082    *
1083    * \param gc the garbage collector to use
1084    * \return the output pin corresponding to the field reference
1085    */
1086     boost::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc)
1087     {
1088       if (instantDataFilter || field_ref.isEmpty())
1089         ERROR("COutputPin* CField::getFieldReference(CGarbageCollector& gc)",
1090               "Impossible to get the field reference for a field which has already been parsed or which does not have a field_ref.");
1091
1092       CField* fieldRef = CField::get(field_ref);
1093       fieldRef->buildFilterGraph(gc, false);
1094
1095       std::pair<boost::shared_ptr<CFilter>, boost::shared_ptr<CFilter> > filters;
1096       // Check if a spatial transformation is needed
1097       if (grid && grid != fieldRef->grid && grid->hasTransform())
1098       {
1099         double defaultValue = !default_value.isEmpty() ? default_value : 0.0;
1100         filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid, grid, defaultValue);
1101       }
1102       else
1103         filters.first = filters.second = boost::shared_ptr<CFilter>(new CPassThroughFilter(gc));
1104
1105       fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0);
1106
1107       return filters.second;
1108     }
1109
1110   /*!
1111    * Returns the filter needed to handle a self reference in the field's expression.
1112    * If the needed filter does not exist, it is created, otherwise it is reused.
1113    * This method should only be called when building the filter graph corresponding
1114    * to the field's expression.
1115    *
1116    * \param gc the garbage collector to use
1117    * \return the output pin corresponding to a self reference
1118    */
1119   boost::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc)
1120   {
1121     if (instantDataFilter || !hasExpression())
1122       ERROR("COutputPin* CField::getSelfReference(CGarbageCollector& gc)",
1123             "Impossible to add a self reference to a field which has already been parsed or which does not have an expression.");
1124
1125     if (!selfReferenceFilter)
1126     {
1127       if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read)
1128       {
1129         if (!serverSourceFilter)
1130           serverSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid,
1131                                                                                   freq_offset.isEmpty() ? NoneDu : freq_offset,
1132                                                                                   true));
1133         selfReferenceFilter = serverSourceFilter;
1134       }
1135       else if (!field_ref.isEmpty())
1136       {
1137         CField* fieldRef = CField::get(field_ref);
1138         fieldRef->buildFilterGraph(gc, false);
1139         selfReferenceFilter = fieldRef->getInstantDataFilter();
1140       }
1141       else
1142       {
1143         if (!clientSourceFilter)
1144           clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid));
1145
1146         selfReferenceFilter = clientSourceFilter;
1147       }
1148     }
1149
1150     return selfReferenceFilter;
1151   }
1152
1153   /*!
1154    * Returns the temporal filter corresponding to the field's temporal operation
1155    * for the specified operation frequency. The filter is created if it does not
1156    * exist, otherwise it is reused.
1157    *
1158    * \param gc the garbage collector to use
1159    * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed
1160    * \return the output pin corresponding to the requested temporal filter
1161    */
1162   boost::shared_ptr<COutputPin> CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)
1163   {
1164     std::map<CDuration, boost::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq);
1165
1166     if (it == temporalDataFilters.end())
1167     {
1168       if (operation.isEmpty())
1169         ERROR("void CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)",
1170               << "An operation must be defined for field \"" << getId() << "\".");
1171
1172       if (freq_op.isEmpty())
1173         freq_op.setValue(TimeStep);
1174       if (freq_offset.isEmpty())
1175         freq_offset.setValue(NoneDu);
1176
1177       const bool ignoreMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true);
1178
1179       boost::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation,
1180                                                                             CContext::getCurrent()->getCalendar()->getInitDate(),
1181                                                                             freq_op, freq_offset, outFreq,
1182                                                                             ignoreMissingValue, ignoreMissingValue ? default_value : 0.0));
1183       instantDataFilter->connectOutput(temporalFilter, 0);
1184
1185       it = temporalDataFilters.insert(std::make_pair(outFreq, temporalFilter)).first;
1186     }
1187
1188     return it->second;
1189   }
1190
1191   //----------------------------------------------------------------
1192/*
1193   void CField::fromBinary(StdIStream& is)
1194   {
1195      SuperClass::fromBinary(is);
1196#define CLEAR_ATT(name_)\
1197      SuperClassAttribute::operator[](#name_)->reset()
1198
1199         CLEAR_ATT(domain_ref);
1200         CLEAR_ATT(axis_ref);
1201#undef CLEAR_ATT
1202
1203   }
1204*/
1205   //----------------------------------------------------------------
1206
1207   void CField::solveGridReference(void)
1208   {
1209      if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty() && scalar_ref.isEmpty())
1210      {
1211        ERROR("CField::solveGridReference(void)",
1212              << "A grid must be defined for field '" << getFieldOutputName() << "' .");
1213      }
1214      else if (!grid_ref.isEmpty() && (!domain_ref.isEmpty() || !axis_ref.isEmpty() || !scalar_ref.isEmpty()))
1215      {
1216        ERROR("CField::solveGridReference(void)",
1217              << "Field '" << getFieldOutputName() << "' has both a grid and a domain/axis/scalar." << std::endl
1218              << "Please define either 'grid_ref' or 'domain_ref'/'axis_ref'/'scalar_ref'.");
1219      }
1220
1221      if (grid_ref.isEmpty())
1222      {
1223        std::vector<CDomain*> vecDom;
1224        std::vector<CAxis*> vecAxis;
1225        std::vector<CScalar*> vecScalar;
1226        std::vector<int> axisDomainOrderTmp;
1227       
1228        if (!domain_ref.isEmpty())
1229        {
1230          StdString tmp = domain_ref.getValue();
1231          if (CDomain::has(domain_ref))
1232          {
1233            vecDom.push_back(CDomain::get(domain_ref));
1234            axisDomainOrderTmp.push_back(2);
1235          }
1236          else
1237            ERROR("CField::solveGridReference(void)",
1238                  << "Invalid reference to domain '" << domain_ref.getValue() << "'.");
1239        }
1240
1241        if (!axis_ref.isEmpty())
1242        {
1243          if (CAxis::has(axis_ref))
1244          {
1245            vecAxis.push_back(CAxis::get(axis_ref));
1246            axisDomainOrderTmp.push_back(1);
1247          }
1248          else
1249            ERROR("CField::solveGridReference(void)",
1250                  << "Invalid reference to axis '" << axis_ref.getValue() << "'.");
1251        }
1252
1253        if (!scalar_ref.isEmpty())
1254        {
1255          if (CScalar::has(scalar_ref))
1256          {
1257            vecScalar.push_back(CScalar::get(scalar_ref));
1258            axisDomainOrderTmp.push_back(0);
1259          }
1260          else
1261            ERROR("CField::solveGridReference(void)",
1262                  << "Invalid reference to scalar '" << scalar_ref.getValue() << "'.");
1263        }
1264       
1265        CArray<int,1> axisDomainOrder(axisDomainOrderTmp.size());
1266        for (int idx = 0; idx < axisDomainOrderTmp.size(); ++idx)
1267        {
1268          axisDomainOrder(idx) = axisDomainOrderTmp[idx];
1269        }
1270
1271        // Warning: the gridId shouldn't be set as the grid_ref since it could be inherited
1272        StdString gridId = CGrid::generateId(vecDom, vecAxis, vecScalar,axisDomainOrder);
1273        if (CGrid::has(gridId))
1274          this->grid = CGrid::get(gridId);
1275        else
1276          this->grid = CGrid::createGrid(gridId, vecDom, vecAxis, vecScalar,axisDomainOrder);
1277      }
1278      else
1279      {
1280        if (CGrid::has(grid_ref))
1281          this->grid = CGrid::get(grid_ref);
1282        else
1283          ERROR("CField::solveGridReference(void)",
1284                << "Invalid reference to grid '" << grid_ref.getValue() << "'.");
1285      }
1286   }
1287
1288   void CField::solveGridDomainAxisRef(bool checkAtt)
1289   {
1290     grid->solveDomainAxisRef(checkAtt);
1291   }
1292
1293   void CField::solveCheckMaskIndex(bool doSendingIndex)
1294   {
1295     grid->checkMaskIndex(doSendingIndex);
1296   }
1297
1298   void CField::solveTransformedGrid()
1299   {
1300     if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid)
1301     {
1302       std::vector<CGrid*> grids;
1303       // Source grid
1304       grids.push_back(getDirectFieldReference()->grid);
1305       // Intermediate grids
1306       if (!grid_path.isEmpty())
1307       {
1308         std::string gridId;
1309         size_t start = 0, end;
1310
1311         do
1312         {
1313           end = grid_path.getValue().find(',', start);
1314           if (end != std::string::npos)
1315           {
1316             gridId = grid_path.getValue().substr(start, end - start);
1317             start = end + 1;
1318           }
1319           else
1320             gridId = grid_path.getValue().substr(start);
1321
1322           if (!CGrid::has(gridId))
1323             ERROR("void CField::solveTransformedGrid()",
1324                   << "Invalid grid_path, the grid '" << gridId << "' does not exist.");
1325
1326           grids.push_back(CGrid::get(gridId));
1327         }
1328         while (end != std::string::npos);
1329       }
1330       // Destination grid
1331       grids.push_back(grid);
1332
1333       for (size_t i = 0, count = grids.size() - 1; i < count; ++i)
1334       {
1335         CGrid *gridSrc  = grids[i];
1336         CGrid *gridDest = grids[i + 1];
1337         if (!gridDest->isTransformed())
1338           gridDest->transformGrid(gridSrc);
1339       }
1340     }
1341     else if (grid && grid->hasTransform() && !grid->isTransformed())
1342     {
1343       // Temporarily deactivate the self-transformation of grid
1344       //grid->transformGrid(grid);
1345     }
1346   }
1347
1348   void CField::solveGenerateGrid()
1349   {
1350     if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid)
1351       grid->completeGrid(getDirectFieldReference()->grid);
1352     else
1353       grid->completeGrid();
1354   }
1355
1356   void CField::solveGridDomainAxisBaseRef()
1357   {
1358     grid->solveDomainAxisRef(false);
1359     grid->solveDomainAxisBaseRef();
1360   }
1361
1362   ///-------------------------------------------------------------------
1363
1364   template <>
1365   void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
1366   {
1367      if (this->group_ref.isEmpty()) return;
1368      StdString gref = this->group_ref.getValue();
1369
1370      if (!CFieldGroup::has(gref))
1371         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
1372               << "[ gref = " << gref << "]"
1373               << " invalid group name !");
1374
1375      CFieldGroup* group = CFieldGroup::get(gref);
1376      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
1377
1378      std::vector<CField*> allChildren  = group->getAllChildren();
1379      std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end();
1380
1381      for (; it != end; it++)
1382      {
1383         CField* child = *it;
1384         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId());
1385
1386      }
1387   }
1388
1389   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
1390   {
1391     map<int, CArray<double,1> >::iterator it;
1392     for (it = data_srv.begin(); it != data_srv.end(); it++) it->second = (it->second - addOffset) / scaleFactor;
1393   }
1394
1395   void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset)
1396   {
1397     map<int, CArray<double,1> >::iterator it;
1398     for (it = data_srv.begin(); it != data_srv.end(); it++) it->second = it->second * scaleFactor + addOffset;
1399   }
1400
1401   void CField::outputField(CArray<double,3>& fieldOut)
1402   {
1403      map<int, CArray<double,1> >::iterator it;
1404      for (it = data_srv.begin(); it != data_srv.end(); it++)
1405      {
1406        grid->outputField(it->first, it->second, fieldOut.dataFirst());
1407      }
1408   }
1409
1410   void CField::outputField(CArray<double,2>& fieldOut)
1411   {
1412      map<int, CArray<double,1> >::iterator it;
1413      for(it=data_srv.begin();it!=data_srv.end();it++)
1414      {
1415         grid->outputField(it->first, it->second, fieldOut.dataFirst());
1416      }
1417   }
1418
1419   void CField::outputField(CArray<double,1>& fieldOut)
1420   {
1421      // map<int, CArray<double,1> >::iterator it;
1422
1423      // for (it = data_srv.begin(); it != data_srv.end(); it++)
1424      // {
1425      //    grid->outputField(it->first, it->second, fieldOut.dataFirst());
1426      // }
1427    grid->outputField(recvDataSrv, fieldOut);
1428   }
1429
1430   void CField::inputField(CArray<double,3>& fieldOut)
1431   {
1432      map<int, CArray<double,1> >::iterator it;
1433      for (it = data_srv.begin(); it != data_srv.end(); it++)
1434      {
1435        grid->inputField(it->first, fieldOut.dataFirst(), it->second);
1436      }
1437   }
1438
1439   void CField::inputField(CArray<double,2>& fieldOut)
1440   {
1441      map<int, CArray<double,1> >::iterator it;
1442      for(it = data_srv.begin(); it != data_srv.end(); it++)
1443      {
1444         grid->inputField(it->first, fieldOut.dataFirst(), it->second);
1445      }
1446   }
1447
1448   void CField::inputField(CArray<double,1>& fieldOut)
1449   {
1450      map<int, CArray<double,1> >::iterator it;
1451      for (it = data_srv.begin(); it != data_srv.end(); it++)
1452      {
1453         grid->inputField(it->first, fieldOut.dataFirst(), it->second);
1454      }
1455   }
1456
1457   void CField::outputCompressedField(CArray<double,1>& fieldOut)
1458   {
1459      map<int, CArray<double,1> >::iterator it;
1460
1461      for (it = data_srv.begin(); it != data_srv.end(); it++)
1462      {
1463         grid->outputCompressedField(it->first, it->second, fieldOut.dataFirst());
1464      }
1465   }
1466
1467   ///-------------------------------------------------------------------
1468
1469   void CField::parse(xml::CXMLNode& node)
1470   {
1471      SuperClass::parse(node);
1472      if (!node.getContent(this->content))
1473      {
1474        if (node.goToChildElement())
1475        {
1476          do
1477          {
1478            if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node);
1479          } while (node.goToNextElement());
1480          node.goToParentElement();
1481        }
1482      }
1483    }
1484
1485   /*!
1486     This function retrieves Id of corresponding domain_ref and axis_ref (if any)
1487   of a field. In some cases, only domain exists but axis doesn't
1488   \return pair of Domain and Axis id
1489   */
1490   const std::vector<StdString>& CField::getRefDomainAxisIds()
1491   {
1492     CGrid* cgPtr = getRelGrid();
1493     if (NULL != cgPtr)
1494     {
1495       std::vector<StdString>::iterator it;
1496       if (!domain_ref.isEmpty())
1497       {
1498         std::vector<StdString> domainList = cgPtr->getDomainList();
1499         it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue());
1500         if (domainList.end() != it) domAxisScalarIds_[0] = *it;
1501       }
1502
1503       if (!axis_ref.isEmpty())
1504       {
1505         std::vector<StdString> axisList = cgPtr->getAxisList();
1506         it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue());
1507         if (axisList.end() != it) domAxisScalarIds_[1] = *it;
1508       }
1509
1510       if (!scalar_ref.isEmpty())
1511       {
1512         std::vector<StdString> scalarList = cgPtr->getScalarList();
1513         it = std::find(scalarList.begin(), scalarList.end(), scalar_ref.getValue());
1514         if (scalarList.end() != it) domAxisScalarIds_[2] = *it;
1515       }
1516     }
1517     return (domAxisScalarIds_);
1518   }
1519
1520   CVariable* CField::addVariable(const string& id)
1521   {
1522     return vVariableGroup->createChild(id);
1523   }
1524
1525   CVariableGroup* CField::addVariableGroup(const string& id)
1526   {
1527     return vVariableGroup->createChildGroup(id);
1528   }
1529
1530   void CField::sendAddAllVariables()
1531   {
1532     std::vector<CVariable*> allVar = getAllVariables();
1533     std::vector<CVariable*>::const_iterator it = allVar.begin();
1534     std::vector<CVariable*>::const_iterator itE = allVar.end();
1535
1536     for (; it != itE; ++it)
1537     {
1538       this->sendAddVariable((*it)->getId());
1539       (*it)->sendAllAttributesToServer();
1540       (*it)->sendValue();
1541     }
1542   }
1543
1544   void CField::sendAddAllVariables(CContextClient* client)
1545   {
1546     std::vector<CVariable*> allVar = getAllVariables();
1547     std::vector<CVariable*>::const_iterator it = allVar.begin();
1548     std::vector<CVariable*>::const_iterator itE = allVar.end();
1549
1550     for (; it != itE; ++it)
1551     {
1552       this->sendAddVariable((*it)->getId(), client);
1553       (*it)->sendAllAttributesToServer(client);
1554       (*it)->sendValue(client);
1555     }
1556   }
1557
1558   void CField::sendAddVariable(const string& id)
1559   {
1560      sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE);
1561    // CContext* context = CContext::getCurrent();
1562
1563    // if (!context->hasServer)
1564    // {
1565    //    CContextClient* client = context->client;
1566
1567    //    CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
1568    //    if (client->isServerLeader())
1569    //    {
1570    //      CMessage msg;
1571    //      msg << this->getId();
1572    //      msg << id;
1573    //      const std::list<int>& ranks = client->getRanksServerLeader();
1574    //      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1575    //        event.push(*itRank,1,msg);
1576    //      client->sendEvent(event);
1577    //    }
1578    //    else client->sendEvent(event);
1579    // }
1580   }
1581
1582   void CField::sendAddVariable(const string& id, CContextClient* client)
1583   {
1584      sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE, client);
1585    // CContext* context = CContext::getCurrent();
1586
1587    // if (!context->hasServer)
1588    // {
1589    //    CContextClient* client = context->client;
1590
1591    //    CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
1592    //    if (client->isServerLeader())
1593    //    {
1594    //      CMessage msg;
1595    //      msg << this->getId();
1596    //      msg << id;
1597    //      const std::list<int>& ranks = client->getRanksServerLeader();
1598    //      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1599    //        event.push(*itRank,1,msg);
1600    //      client->sendEvent(event);
1601    //    }
1602    //    else client->sendEvent(event);
1603    // }
1604   }
1605
1606   void CField::sendAddVariableGroup(const string& id)
1607   {
1608      sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE_GROUP);
1609    // CContext* context = CContext::getCurrent();
1610    // if (!context->hasServer)
1611    // {
1612    //    CContextClient* client = context->client;
1613
1614    //    CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP);
1615    //    if (client->isServerLeader())
1616    //    {
1617    //      CMessage msg;
1618    //      msg << this->getId();
1619    //      msg << id;
1620    //      const std::list<int>& ranks = client->getRanksServerLeader();
1621    //      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1622    //        event.push(*itRank,1,msg);
1623    //      client->sendEvent(event);
1624    //    }
1625    //    else client->sendEvent(event);
1626    // }
1627   }
1628
1629   void CField::recvAddVariable(CEventServer& event)
1630   {
1631
1632      CBufferIn* buffer = event.subEvents.begin()->buffer;
1633      string id;
1634      *buffer >> id;
1635      get(id)->recvAddVariable(*buffer);
1636   }
1637
1638   void CField::recvAddVariable(CBufferIn& buffer)
1639   {
1640      string id;
1641      buffer >> id;
1642      addVariable(id);
1643   }
1644
1645   void CField::recvAddVariableGroup(CEventServer& event)
1646   {
1647
1648      CBufferIn* buffer = event.subEvents.begin()->buffer;
1649      string id;
1650      *buffer >> id;
1651      get(id)->recvAddVariableGroup(*buffer);
1652   }
1653
1654   void CField::recvAddVariableGroup(CBufferIn& buffer)
1655   {
1656      string id;
1657      buffer >> id;
1658      addVariableGroup(id);
1659   }
1660
1661   /*!
1662    * Returns string arithmetic expression associated to the field.
1663    * \return if content is defined return content string, otherwise, if "expr" attribute is defined, return expr string.
1664    */
1665   const string& CField::getExpression(void)
1666   {
1667     if (!expr.isEmpty() && content.empty())
1668     {
1669       content = expr;
1670       expr.reset();
1671     }
1672
1673     return content;
1674   }
1675
1676   bool CField::hasExpression(void) const
1677   {
1678     return (!expr.isEmpty() || !content.empty());
1679   }
1680
1681
1682   DEFINE_REF_FUNC(Field,field)
1683} // namespace xios
Note: See TracBrowser for help on using the repository browser.