source: XIOS/trunk/src/node/field.cpp @ 658

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

Field: Avoid some heap allocations.

  • 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: 30.4 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
26namespace xios{
27
28   /// ////////////////////// Définitions ////////////////////// ///
29
30   CField::CField(void)
31      : CObjectTemplate<CField>(), CFieldAttributes()
32      , refObject(), baseRefObject()
33      , grid(), file()
34      , nstep(0), nstepMax(0)
35      , hasOutputFile(false)
36      , domAxisIds_("", ""), areAllReferenceSolved(false)
37      , isReadDataRequestPending(false)
38   { setVirtualVariableGroup(); }
39
40   CField::CField(const StdString& id)
41      : CObjectTemplate<CField>(id), CFieldAttributes()
42      , refObject(), baseRefObject()
43      , grid(), file()
44      , nstep(0), nstepMax(0)
45      , hasOutputFile(false)
46      , domAxisIds_("", ""), areAllReferenceSolved(false)
47      , isReadDataRequestPending(false)
48   { setVirtualVariableGroup(); }
49
50   CField::~CField(void)
51   {}
52
53  //----------------------------------------------------------------
54
55   void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
56   {
57      this->vVariableGroup = newVVariableGroup;
58   }
59
60   void CField::setVirtualVariableGroup(void)
61   {
62      this->setVirtualVariableGroup(CVariableGroup::create());
63   }
64
65   CVariableGroup* CField::getVirtualVariableGroup(void) const
66   {
67      return this->vVariableGroup;
68   }
69
70
71   std::vector<CVariable*> CField::getAllVariables(void) const
72   {
73      return this->vVariableGroup->getAllChildren();
74   }
75
76   void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent)
77   {
78      SuperClassAttribute::setAttributes(parent, apply);
79      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
80   }
81
82  //----------------------------------------------------------------
83
84  bool CField::dispatchEvent(CEventServer& event)
85  {
86    if (SuperClass::dispatchEvent(event)) return true;
87    else
88    {
89      switch(event.type)
90      {
91        case EVENT_ID_UPDATE_DATA :
92          recvUpdateData(event);
93          return true;
94          break;
95
96        case EVENT_ID_READ_DATA :
97          recvReadDataRequest(event);
98          return true;
99          break;
100
101        case EVENT_ID_READ_DATA_READY :
102          recvReadDataReady(event);
103          return true;
104          break;
105
106        case EVENT_ID_ADD_VARIABLE :
107          recvAddVariable(event);
108          return true;
109          break;
110
111        case EVENT_ID_ADD_VARIABLE_GROUP :
112          recvAddVariableGroup(event);
113          return true;
114          break;
115
116        default :
117          ERROR("bool CField::dispatchEvent(CEventServer& event)", << "Unknown Event");
118          return false;
119      }
120    }
121  }
122
123  void CField::sendUpdateData(const CArray<double,1>& data)
124  {
125    CTimer::get("XIOS Send Data").resume();
126
127    CContext* context = CContext::getCurrent();
128    CContextClient* client = context->client;
129
130    CEventClient event(getType(), EVENT_ID_UPDATE_DATA);
131
132    map<int, CArray<int,1> >::iterator it;
133    list<CMessage> list_msg;
134    list<CArray<double,1> > list_data;
135
136    if (!grid->doGridHaveDataDistributed())
137    {
138       if (0 == client->clientRank)
139       {
140          for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
141          {
142            int rank = it->first;
143            CArray<int,1>& index = it->second;
144
145            list_msg.push_back(CMessage());
146            list_data.push_back(CArray<double,1>(index.numElements()));
147
148            CArray<double,1>& data_tmp = list_data.back();
149            for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
150
151            list_msg.back() << getId() << data_tmp;
152            event.push(rank, 1, list_msg.back());
153          }
154          client->sendEvent(event);
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[rank], list_msg.back());
172      }
173      client->sendEvent(event);
174    }
175   
176    CTimer::get("XIOS Send Data").suspend();
177  }
178
179  void CField::recvUpdateData(CEventServer& event)
180  {
181    vector<int> ranks;
182    vector<CBufferIn*> buffers;
183
184    list<CEventServer::SSubEvent>::iterator it;
185    string fieldId;
186
187    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
188    {
189      int rank = it->rank;
190      CBufferIn* buffer = it->buffer;
191      *buffer >> fieldId;
192      ranks.push_back(rank);
193      buffers.push_back(buffer);
194    }
195    get(fieldId)->recvUpdateData(ranks,buffers);
196  }
197
198  void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
199  {
200    if (data_srv.empty())
201    {
202      for (map<int, CArray<size_t, 1> >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
203      {
204        int rank = it->first;
205        data_srv.insert(std::make_pair(rank, CArray<double,1>(it->second.numElements())));
206        foperation_srv.insert(pair<int,boost::shared_ptr<func::CFunctor> >(rank,boost::shared_ptr<func::CFunctor>(new func::CInstant(data_srv[rank]))));
207      }
208    }
209
210    CContext* context = CContext::getCurrent();
211    const CDate& currDate = context->getCalendar()->getCurrentDate();
212    const CDate opeDate      = last_operation_srv + freq_operation_srv;
213    const CDate writeDate    = last_Write_srv     + freq_write_srv;
214
215    if (opeDate <= currDate)
216    {
217      for (int n = 0; n < ranks.size(); n++)
218      {
219        CArray<double,1> data_tmp;
220        *buffers[n] >> data_tmp;
221        (*foperation_srv[ranks[n]])(data_tmp);
222      }
223      last_operation_srv = currDate;
224    }
225
226    if (writeDate < (currDate + freq_operation_srv))
227    {
228      for (int n = 0; n < ranks.size(); n++)
229      {
230        this->foperation_srv[ranks[n]]->final();
231      }
232
233      last_Write_srv = writeDate;
234      writeField();
235      lastlast_Write_srv = last_Write_srv;
236    }
237  }
238
239  void CField::writeField(void)
240  {
241    if (!getRelFile()->allDomainEmpty)
242    {
243      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
244      {
245        getRelFile()->checkFile();
246        this->incrementNStep();
247        getRelFile()->getDataOutput()->writeFieldData(CField::get(this));
248      }
249    }
250  }
251
252  void CField::sendReadDataRequest(void)
253  {
254    CContext* context = CContext::getCurrent();
255    CContextClient* client = context->client;
256
257    CEventClient event(getType(), EVENT_ID_READ_DATA);
258    if (client->isServerLeader())
259    {
260      CMessage msg;
261      msg << getId();
262      const std::list<int>& ranks = client->getRanksServerLeader();
263      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
264        event.push(*itRank, 1, msg);
265      client->sendEvent(event);
266    }
267    else client->sendEvent(event);
268
269    lastDataRequestedFromServer = context->getCalendar()->getCurrentDate();
270    isReadDataRequestPending = true;
271  }
272
273  /*!
274  Send request new data read from file if need be, that is the current data is out-of-date.
275  \return true if and only if some data was requested
276  */
277  bool CField::sendReadDataRequestIfNeeded(void)
278  {
279    const CDate& currentDate = CContext::getCurrent()->getCalendar()->getCurrentDate();
280
281    bool requestData = (currentDate >= lastDataRequestedFromServer + file->output_freq.getValue());
282
283    if (requestData)
284      sendReadDataRequest();
285
286    return requestData;
287  }
288
289  void CField::recvReadDataRequest(CEventServer& event)
290  {
291    CBufferIn* buffer = event.subEvents.begin()->buffer;
292    StdString fieldId;
293    *buffer >> fieldId;
294    get(fieldId)->recvReadDataRequest();
295  }
296
297  void CField::recvReadDataRequest(void)
298  {
299    CContext* context = CContext::getCurrent();
300    CContextClient* client = context->client;
301
302    CEventClient event(getType(), EVENT_ID_READ_DATA_READY);
303    std::list<CMessage> msgs;
304
305    bool hasData = readField();
306
307    map<int, CArray<double,1> >::iterator it;
308    for (it = data_srv.begin(); it != data_srv.end(); it++)
309    {
310      msgs.push_back(CMessage());
311      CMessage& msg = msgs.back();
312      msg << getId();
313      if (hasData)
314        msg << getNStep() - 1 << it->second;
315      else
316        msg << size_t(-1);
317      event.push(it->first, grid->nbSenders[it->first], msg);
318    }
319    client->sendEvent(event);
320  }
321
322  bool CField::readField(void)
323  {
324    if (!getRelFile()->allDomainEmpty)
325    {
326      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
327      {
328        if (data_srv.empty())
329        {
330          for (map<int, CArray<size_t, 1> >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
331            data_srv.insert(std::make_pair(it->first, CArray<double,1>(it->second.numElements())));
332        }
333
334        getRelFile()->checkFile();
335        this->incrementNStep();
336
337        if (!nstepMax)
338        {
339          nstepMax = getRelFile()->getDataInput()->getFieldNbRecords(CField::get(this));
340        }
341
342        if (getNStep() > nstepMax)
343          return false;
344
345        getRelFile()->getDataInput()->readFieldData(CField::get(this));
346      }
347    }
348
349    return true;
350  }
351
352  void CField::recvReadDataReady(CEventServer& event)
353  {
354    string fieldId;
355    vector<int> ranks;
356    vector<CBufferIn*> buffers;
357
358    list<CEventServer::SSubEvent>::iterator it;
359    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
360    {
361      ranks.push_back(it->rank);
362      CBufferIn* buffer = it->buffer;
363      *buffer >> fieldId;
364      buffers.push_back(buffer);
365    }
366    get(fieldId)->recvReadDataReady(ranks, buffers);
367  }
368
369  void CField::recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers)
370  {
371    CContext* context = CContext::getCurrent();
372    StdSize record;
373    std::map<int, CArray<double,1> > data;
374
375    bool isEOF = false;
376
377    for (int i = 0; i < ranks.size(); i++)
378    {
379      int rank = ranks[i];
380      *buffers[i] >> record;
381      isEOF = (record == size_t(-1));
382
383      if (!isEOF)
384        *buffers[i] >> data[rank];
385      else
386        break;
387    }
388
389    if (isEOF)
390      serverSourceFilter->signalEndOfStream(lastDataRequestedFromServer);
391    else
392      serverSourceFilter->streamDataFromServer(lastDataRequestedFromServer, data);
393
394    isReadDataRequestPending = false;
395  }
396
397   //----------------------------------------------------------------
398
399   void CField::setRelFile(CFile* _file)
400   {
401      this->file = _file;
402      hasOutputFile = true;
403   }
404
405   //----------------------------------------------------------------
406
407   StdString CField::GetName(void)    { return StdString("field"); }
408   StdString CField::GetDefName(void) { return CField::GetName(); }
409   ENodeType CField::GetType(void)    { return eField; }
410
411   //----------------------------------------------------------------
412
413   CGrid* CField::getRelGrid(void) const
414   {
415      return this->grid;
416   }
417
418   //----------------------------------------------------------------
419
420   CFile* CField::getRelFile(void) const
421   {
422      return this->file;
423   }
424
425   StdSize CField::getNStep(void) const
426   {
427      return this->nstep;
428   }
429
430   func::CFunctor::ETimeType CField::getOperationTimeType() const
431   {
432     return operationTimeType;
433   }
434
435   //----------------------------------------------------------------
436
437   void CField::incrementNStep(void)
438   {
439      this->nstep++;
440   }
441
442   void CField::resetNStep(void)
443   {
444      this->nstep = 0;
445   }
446
447   void CField::resetNStepMax(void)
448   {
449      this->nstepMax = 0;
450   }
451
452   //----------------------------------------------------------------
453
454   bool CField::isActive(void) const
455   {
456      return !this->refObject.empty();
457   }
458
459   //----------------------------------------------------------------
460
461   boost::shared_ptr<COutputPin> CField::getInstantDataFilter()
462   {
463     return instantDataFilter;
464   }
465
466   //----------------------------------------------------------------
467
468   void CField::solveAllReferenceEnabledField(bool doSending2Sever)
469   {
470     CContext* context = CContext::getCurrent();
471     if (!areAllReferenceSolved)
472     {
473        areAllReferenceSolved = true;
474
475        if (context->hasClient)
476        {
477          solveRefInheritance(true);
478          solveBaseReference();
479          if (hasDirectFieldReference()) getDirectFieldReference()->solveAllReferenceEnabledField(false);
480        }
481        else if (context->hasServer)
482          solveServerOperation();
483
484        solveGridReference();
485     }
486     solveGridDomainAxisRef(doSending2Sever);
487     if (context->hasClient)
488     {
489       solveTransformedGrid();
490     }
491     solveCheckMaskIndex(doSending2Sever);
492   }
493
494   std::map<int, StdSize> CField::getGridDataSize()
495   {
496     return grid->getConnectedServerDataSize();
497   }
498
499   //----------------------------------------------------------------
500
501   void CField::solveServerOperation(void)
502   {
503      CContext* context = CContext::getCurrent();
504
505      if (!context->hasServer || !hasOutputFile) return;
506
507      if (freq_op.isEmpty())
508        freq_op.setValue(TimeStep);
509
510      if (freq_offset.isEmpty())
511        freq_offset.setValue(NoneDu);
512
513      freq_operation_srv = file->output_freq.getValue();
514      freq_write_srv     = file->output_freq.getValue();
515
516      lastlast_Write_srv = context->getCalendar()->getInitDate();
517      last_Write_srv     = context->getCalendar()->getInitDate();
518      last_operation_srv = context->getCalendar()->getInitDate();
519
520      const CDuration toffset = freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
521      last_operation_srv     = last_operation_srv - toffset;
522
523      if (operation.isEmpty())
524        ERROR("void CField::solveServerOperation(void)",
525              << "An operation must be defined for field \"" << getId() << "\".");
526
527      boost::shared_ptr<func::CFunctor> functor;
528      CArray<double, 1> dummyData;
529
530#define DECLARE_FUNCTOR(MType, mtype) \
531      if (operation.getValue().compare(#mtype) == 0) \
532      { \
533        functor.reset(new func::C##MType(dummyData)); \
534      }
535
536#include "functor_type.conf"
537
538      if (!functor)
539        ERROR("void CField::solveServerOperation(void)",
540              << "\"" << operation << "\" is not a valid operation.");
541
542      operationTimeType = functor->timeType();
543   }
544
545   //----------------------------------------------------------------
546
547   /*!
548    * Constructs the graph filter for the field, enabling or not the data output.
549    * This method should not be called more than once with enableOutput equal to true.
550    *
551    * \param gc the garbage collector to use when building the filter graph
552    * \param enableOutput must be true when the field data is to be
553    *                     read by the client or/and written to a file
554    */
555   void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput)
556   {
557     if (!areAllReferenceSolved) solveAllReferenceEnabledField(false);
558
559     // Start by building a filter which can provide the field's instant data
560     if (!instantDataFilter)
561     {
562       // Check if we have an expression to parse
563       if (!content.empty())
564       {
565         boost::scoped_ptr<IFilterExprNode> expr(parseExpr(content + '\0'));
566         instantDataFilter = expr->reduce(gc, *this);
567       }
568       // Check if we have a reference on another field
569       else if (!field_ref.isEmpty())
570       {
571         CField* fieldRef = CField::get(field_ref);
572         fieldRef->buildFilterGraph(gc, false);
573
574         std::pair<boost::shared_ptr<CFilter>, boost::shared_ptr<CFilter> > filters;
575         // Check if a spatial transformation is needed
576         if (!grid_ref.isEmpty() && !fieldRef->grid_ref.isEmpty() && grid_ref.getValue() != fieldRef->grid_ref.getValue())
577           filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid, grid);
578         else
579           filters.first = filters.second = boost::shared_ptr<CFilter>(new CPassThroughFilter(gc));
580
581         fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0);
582         instantDataFilter = filters.second;
583       }
584       // Check if the data is to be read from a file
585       else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read)
586         instantDataFilter = serverSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(grid));
587       else // The data might be passed from the model
588         instantDataFilter = clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(grid));
589     }
590
591     // If the field data is to be read by the client or/and written to a file
592     if (enableOutput && !storeFilter && !fileWriterFilter)
593     {
594       if (!read_access.isEmpty() && read_access.getValue())
595       {
596         storeFilter = boost::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid));
597         instantDataFilter->connectOutput(storeFilter, 0);
598       }
599
600       if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write))
601       {
602         fileWriterFilter = boost::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this));
603         getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0);
604       }
605     }
606   }
607
608   /*!
609    * Returns the source filter to handle a self reference in the field's expression.
610    * If the needed source filter does not exist, it is created, otherwise it is reused.
611    * This method should only be called when building the filter graph corresponding
612    * to the field's expression.
613    *
614    * \param gc the garbage collector to use
615    * \return the output pin corresponding to a self reference
616    */
617   boost::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc)
618   {
619     if (instantDataFilter || content.empty())
620       ERROR("COutputPin* CField::getSelfReference(CGarbageCollector& gc)",
621             "Impossible to add a self reference to a field which has already been parsed or which does not have an expression.");
622
623     if (!clientSourceFilter)
624       clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(grid));
625
626     return clientSourceFilter;
627   }
628
629   /*!
630    * Returns the temporal filter corresponding to the field's temporal operation
631    * for the specified operation frequency. The filter is created if it does not
632    * exist, otherwise it is reused.
633    *
634    * \param gc the garbage collector to use
635    * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed
636    * \return the output pin corresponding to the requested temporal filter
637    */
638   boost::shared_ptr<COutputPin> CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)
639   {
640     std::map<CDuration, boost::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq);
641
642     if (it == temporalDataFilters.end())
643     {
644       if (operation.isEmpty())
645         ERROR("void CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)",
646               << "An operation must be defined for field \"" << getId() << "\".");
647
648       if (freq_op.isEmpty())
649         freq_op.setValue(TimeStep);
650       if (freq_offset.isEmpty())
651         freq_offset.setValue(NoneDu);
652
653       const bool ignoreMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true);
654
655       boost::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation,
656                                                                             CContext::getCurrent()->getCalendar()->getInitDate(),
657                                                                             freq_op, freq_offset, outFreq,
658                                                                             ignoreMissingValue, ignoreMissingValue ? default_value : 0.0));
659       instantDataFilter->connectOutput(temporalFilter, 0);
660
661       it = temporalDataFilters.insert(std::make_pair(outFreq, temporalFilter)).first;
662     }
663
664     return it->second;
665   }
666
667   //----------------------------------------------------------------
668/*
669   void CField::fromBinary(StdIStream& is)
670   {
671      SuperClass::fromBinary(is);
672#define CLEAR_ATT(name_)\
673      SuperClassAttribute::operator[](#name_)->reset()
674
675         CLEAR_ATT(domain_ref);
676         CLEAR_ATT(axis_ref);
677#undef CLEAR_ATT
678
679   }
680*/
681   //----------------------------------------------------------------
682
683   void CField::solveGridReference(void)
684   {
685      CDomain* domain;
686      CAxis* axis;
687      std::vector<CDomain*> vecDom;
688      std::vector<CAxis*> vecAxis;
689      std::vector<std::string> domList, axisList;
690
691      if (!domain_ref.isEmpty())
692      {
693         if (CDomain::has(domain_ref.getValue()))
694         {
695           domain = CDomain::get(domain_ref.getValue());
696           vecDom.push_back(domain);
697         }
698         else
699            ERROR("CField::solveGridReference(void)",
700                  << "Reference to the domain \'"
701                  << domain_ref.getValue() << "\' is wrong");
702      }
703
704      if (!axis_ref.isEmpty())
705      {
706         if (CAxis::has(axis_ref.getValue()))
707         {
708           axis = CAxis::get(axis_ref.getValue());
709           vecAxis.push_back(axis);
710         }
711         else
712            ERROR("CField::solveGridReference(void)",
713                  << "Reference to the axis \'"
714                  << axis_ref.getValue() <<"\' is wrong");
715      }
716
717      if (!grid_ref.isEmpty())
718      {
719         if (CGrid::has(grid_ref.getValue()))
720         {
721           this->grid = CGrid::get(grid_ref.getValue());
722           domList = grid->getDomainList();
723           axisList = grid->getAxisList();
724           if (domList.empty() && axisList.empty())
725           {
726             this->grid = CGrid::createGrid(vecDom, vecAxis);
727           }
728         }
729         else
730            ERROR("CField::solveGridReference(void)",
731                  << "Reference to the grid \'"
732                  << grid_ref.getValue() << "\' is wrong");
733      }
734      else
735      {
736         this->grid = CGrid::createGrid(vecDom, vecAxis);
737      }
738
739      if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty())
740      {
741            ERROR("CField::solveGridReference(void)",
742                  << "At least one dimension must be defined for this field.");
743      }
744   }
745
746   void CField::solveGridDomainAxisRef(bool checkAtt)
747   {
748     grid->solveDomainAxisRef(checkAtt);
749   }
750
751   void CField::solveCheckMaskIndex(bool doSendingIndex)
752   {
753     grid->checkMaskIndex(doSendingIndex);
754   }
755
756   void CField::solveTransformedGrid()
757   {
758     if (!grid_ref.isEmpty() && hasDirectFieldReference() && !getDirectFieldReference()->grid_ref.isEmpty()
759         && grid_ref.getValue() != getDirectFieldReference()->grid_ref.getValue() && !grid->isTransformed())
760       grid->transformGrid(getDirectFieldReference()->grid);
761   }
762
763   ///-------------------------------------------------------------------
764
765   template <>
766   void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
767   {
768      if (this->group_ref.isEmpty()) return;
769      StdString gref = this->group_ref.getValue();
770
771      if (!CFieldGroup::has(gref))
772         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
773               << "[ gref = " << gref << "]"
774               << " invalid group name !");
775
776      CFieldGroup* group = CFieldGroup::get(gref);
777      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
778
779      std::vector<CField*> allChildren  = group->getAllChildren();
780      std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end();
781
782      for (; it != end; it++)
783      {
784         CField* child = *it;
785         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId());
786
787      }
788   }
789
790   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
791   {
792     map<int, CArray<double,1> >::iterator it;
793     for (it = data_srv.begin(); it != data_srv.end(); it++) it->second = (it->second - addOffset) / scaleFactor;
794   }
795
796   void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset)
797   {
798     map<int, CArray<double,1> >::iterator it;
799     for (it = data_srv.begin(); it != data_srv.end(); it++) it->second = it->second * scaleFactor + addOffset;
800   }
801
802   void CField::outputField(CArray<double,3>& fieldOut)
803   {
804      map<int, CArray<double,1> >::iterator it;
805      for (it = data_srv.begin(); it != data_srv.end(); it++)
806      {
807        grid->outputField(it->first, it->second, fieldOut.dataFirst());
808      }
809   }
810
811   void CField::outputField(CArray<double,2>& fieldOut)
812   {
813      map<int, CArray<double,1> >::iterator it;
814      for(it=data_srv.begin();it!=data_srv.end();it++)
815      {
816         grid->outputField(it->first, it->second, fieldOut.dataFirst()) ;
817      }
818   }
819
820   void CField::outputField(CArray<double,1>& fieldOut)
821   {
822      map<int, CArray<double,1> >::iterator it;
823
824      for (it = data_srv.begin(); it != data_srv.end(); it++)
825      {
826         grid->outputField(it->first, it->second, fieldOut.dataFirst()) ;
827      }
828   }
829
830   void CField::inputField(CArray<double,3>& fieldOut)
831   {
832      map<int, CArray<double,1> >::iterator it;
833      for (it = data_srv.begin(); it != data_srv.end(); it++)
834      {
835        grid->inputField(it->first, fieldOut.dataFirst(), it->second);
836      }
837   }
838
839   void CField::inputField(CArray<double,2>& fieldOut)
840   {
841      map<int, CArray<double,1> >::iterator it;
842      for(it = data_srv.begin(); it != data_srv.end(); it++)
843      {
844         grid->inputField(it->first, fieldOut.dataFirst(), it->second);
845      }
846   }
847
848   void CField::inputField(CArray<double,1>& fieldOut)
849   {
850      map<int, CArray<double,1> >::iterator it;
851      for (it = data_srv.begin(); it != data_srv.end(); it++)
852      {
853         grid->inputField(it->first, fieldOut.dataFirst(), it->second);
854      }
855   }
856
857   ///-------------------------------------------------------------------
858
859   void CField::parse(xml::CXMLNode& node)
860   {
861      SuperClass::parse(node);
862      if (!node.getContent(this->content))
863      {
864        if (node.goToChildElement())
865        {
866          do
867          {
868            if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node);
869          } while (node.goToNextElement());
870          node.goToParentElement();
871        }
872      }
873    }
874
875   /*!
876     This function retrieves Id of corresponding domain_ref and axis_ref (if any)
877   of a field. In some cases, only domain exists but axis doesn't
878   \return pair of Domain and Axis id
879   */
880   const std::pair<StdString,StdString>& CField::getRefDomainAxisIds()
881   {
882     CGrid* cgPtr = getRelGrid();
883     if (NULL != cgPtr)
884     {
885       std::vector<StdString>::iterator it;
886       if (!domain_ref.isEmpty())
887       {
888         std::vector<StdString> domainList = cgPtr->getDomainList();
889         it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue());
890         if (domainList.end() != it) domAxisIds_.first = *it;
891       }
892
893       if (!axis_ref.isEmpty())
894       {
895         std::vector<StdString> axisList = cgPtr->getAxisList();
896         it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue());
897         if (axisList.end() != it) domAxisIds_.second = *it;
898       }
899     }
900     return (domAxisIds_);
901   }
902
903   CVariable* CField::addVariable(const string& id)
904   {
905     return vVariableGroup->createChild(id);
906   }
907
908   CVariableGroup* CField::addVariableGroup(const string& id)
909   {
910     return vVariableGroup->createChildGroup(id);
911   }
912
913   void CField::sendAddAllVariables()
914   {
915     if (!getAllVariables().empty())
916     {
917       // Firstly, it's necessary to add virtual variable group
918       sendAddVariableGroup(getVirtualVariableGroup()->getId());
919
920       // Okie, now we can add to this variable group
921       std::vector<CVariable*> allVar = getAllVariables();
922       std::vector<CVariable*>::const_iterator it = allVar.begin();
923       std::vector<CVariable*>::const_iterator itE = allVar.end();
924
925       for (; it != itE; ++it)
926       {
927         this->sendAddVariable((*it)->getId());
928         (*it)->sendAllAttributesToServer();
929         (*it)->sendValue();
930       }
931     }
932   }
933
934   void CField::sendAddVariable(const string& id)
935   {
936    CContext* context = CContext::getCurrent();
937
938    if (!context->hasServer)
939    {
940       CContextClient* client = context->client;
941
942       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
943       if (client->isServerLeader())
944       {
945         CMessage msg;
946         msg << this->getId();
947         msg << id;
948         const std::list<int>& ranks = client->getRanksServerLeader();
949         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
950           event.push(*itRank,1,msg);
951         client->sendEvent(event);
952       }
953       else client->sendEvent(event);
954    }
955   }
956
957   void CField::sendAddVariableGroup(const string& id)
958   {
959    CContext* context = CContext::getCurrent();
960    if (!context->hasServer)
961    {
962       CContextClient* client = context->client;
963
964       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP);
965       if (client->isServerLeader())
966       {
967         CMessage msg;
968         msg << this->getId();
969         msg << id;
970         const std::list<int>& ranks = client->getRanksServerLeader();
971         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
972           event.push(*itRank,1,msg);
973         client->sendEvent(event);
974       }
975       else client->sendEvent(event);
976    }
977   }
978
979   void CField::recvAddVariable(CEventServer& event)
980   {
981
982      CBufferIn* buffer = event.subEvents.begin()->buffer;
983      string id;
984      *buffer >> id;
985      get(id)->recvAddVariable(*buffer);
986   }
987
988   void CField::recvAddVariable(CBufferIn& buffer)
989   {
990      string id;
991      buffer >> id;
992      addVariable(id);
993   }
994
995   void CField::recvAddVariableGroup(CEventServer& event)
996   {
997
998      CBufferIn* buffer = event.subEvents.begin()->buffer;
999      string id;
1000      *buffer >> id;
1001      get(id)->recvAddVariableGroup(*buffer);
1002   }
1003
1004   void CField::recvAddVariableGroup(CBufferIn& buffer)
1005   {
1006      string id;
1007      buffer >> id;
1008      addVariableGroup(id);
1009   }
1010
1011   DEFINE_REF_FUNC(Field,field)
1012} // namespace xios
Note: See TracBrowser for help on using the repository browser.