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

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

Reading for two-level server

+) Update reading with the changes of grid distribution
+) Correct a minor bug on modification grid mask
+) Do some code cleaning

Test
+) On Curie
+) Work in both mode: classical and two-level
+) Push some *.nc for test_remap

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