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

Last change on this file since 1054 was 1054, checked in by oabramkina, 7 years ago

dev: intermediate commit.

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