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

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