source: XIOS/dev/dev_trunk_graph/src/node/grid.hpp @ 1688

Last change on this file since 1688 was 1653, checked in by oabramkina, 5 years ago

Developments for visualization of XIOS workflow.

Branch is spawned from trunk r1649.

Boost library is used for producing Graphviz DOT files. Current results: a DOT file representing a static workflow. For a complete proof of concept, DOT files for each timestamp should be generated. The necessary information has been collected by XIOS, it only requires rearranging the information for graphing (changes in classes CWorkflowGraph and CGraphviz).

  • 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: 22.8 KB
Line 
1#ifndef __XIOS_CGrid__
2#define __XIOS_CGrid__
3
4/// XIOS headers ///
5#include "xios_spl.hpp"
6#include "group_factory.hpp"
7
8#include "declare_group.hpp"
9#include "domain.hpp"
10#include "axis.hpp"
11#include "scalar.hpp"
12#include "array_new.hpp"
13#include "attribute_array.hpp"
14#include "distribution_server.hpp"
15#include "client_server_mapping.hpp"
16#include "utils.hpp"
17#include "transformation_enum.hpp"
18
19namespace xios {
20
21   /// ////////////////////// Declarations ////////////////////// ///
22
23   class CGridGroup;
24   class CGridAttributes;
25   class CDomainGroup;
26   class CAxisGroup;
27   class CScalarGroup;
28   class CGrid;
29   class CDistributionClient;
30   class CDistributionServer;
31   class CServerDistributionDescription;
32   class CClientServerMapping;
33   class CGridTransformation;
34
35   ///--------------------------------------------------------------
36
37   // Declare/Define CGridAttribute
38   BEGIN_DECLARE_ATTRIBUTE_MAP(CGrid)
39#  include "grid_attribute.conf"
40   END_DECLARE_ATTRIBUTE_MAP(CGrid)
41
42   ///--------------------------------------------------------------
43
44   class CGrid
45      : public CObjectTemplate<CGrid>
46      , public CGridAttributes
47   {
48         /// typedef ///
49         typedef CObjectTemplate<CGrid>   SuperClass;
50         typedef CGridAttributes SuperClassAttribute;
51
52      public:
53
54         typedef CGridAttributes RelAttributes;
55         typedef CGridGroup      RelGroup;
56
57         enum EEventId
58         {
59           EVENT_ID_INDEX, EVENT_ID_ADD_DOMAIN, EVENT_ID_ADD_AXIS, EVENT_ID_ADD_SCALAR
60         };
61
62         /// Constructeurs ///
63         CGrid(void);
64         explicit CGrid(const StdString& id);
65         CGrid(const CGrid& grid);       // Not implemented yet.
66         CGrid(const CGrid* const grid); // Not implemented yet.
67
68         /// Traitements ///
69//         void solveReference(void);
70
71         void checkEligibilityForCompressedOutput();
72
73         void solveDomainAxisRef(bool areAttributesChecked);
74
75         void checkMaskIndex(bool doCalculateIndex);
76
77 //        virtual void toBinary  (StdOStream& os) const;
78//         virtual void fromBinary(StdIStream& is);
79
80         void addRelFileCompressed(const StdString& filename);
81
82         /// Tests ///
83         bool isCompressible(void) const;
84         bool isWrittenCompressed(const StdString& filename) const;
85
86      public:
87
88         /// Accesseurs ///
89         StdSize getDimension(void);
90
91         StdSize  getDataSize(void) const;
92
93         /// Entrees-sorties de champs
94         template <int n>
95         void inputField(const CArray<double,n>& field, CArray<double,1>& stored) const;
96         template <int n>
97         void maskField(const CArray<double,n>& field, CArray<double,1>& stored) const;
98         template <int n>
99         void outputField(const CArray<double,1>& stored, CArray<double,n>& field) const; 
100         template <int n>
101         void uncompressField(const CArray<double,n>& data, CArray<double,1>& outData) const; 
102
103         virtual void parse(xml::CXMLNode& node);
104
105         /// Destructeur ///
106         virtual ~CGrid(void);
107
108      public:
109
110         /// Accesseurs statiques ///
111         static StdString GetName(void);
112         static StdString GetDefName(void);
113
114         static ENodeType GetType(void);
115
116         /// Instanciateurs Statiques ///
117         static CGrid* createGrid(CDomain* domain);
118         static CGrid* createGrid(CDomain* domain, CAxis* axis);
119         static CGrid* createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
120                                  const CArray<int,1>& axisDomainOrder = CArray<int,1>());
121         static CGrid* createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
122                                  const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder = CArray<int,1>());
123         static CGrid* createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
124                                  const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder);
125         static StdString generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
126                                     const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder = CArray<int,1>());
127         static StdString generateId(const CGrid* gridSrc, const CGrid* gridDest);
128         static CGrid* cloneGrid(const StdString& idNewGrid, CGrid* gridSrc);
129
130      public:           
131         void computeIndexServer(void);
132         void computeIndex(void);
133         void computeIndexScalarGrid();
134         void computeWrittenIndex();
135
136         void solveDomainRef(bool checkAtt);
137         void solveAxisRef(bool checkAtt);
138         void solveScalarRef(bool checkAtt);
139         void solveDomainAxisRefInheritance(bool apply = true);
140         void solveTransformations();
141         void solveDomainAxisBaseRef();
142
143         CDomain* addDomain(const std::string& id=StdString());
144         CAxis* addAxis(const std::string& id=StdString());
145         CScalar* addScalar(const std::string& id=StdString());
146         void sendAddDomain(const std::string& id="");
147         void sendAddAxis(const std::string& id="");
148         void sendAddScalar(const std::string& id="");
149         void sendAllDomains();
150         void sendAllAxis();
151         void sendAllScalars();
152
153         static void recvAddDomain(CEventServer& event);
154         void recvAddDomain(CBufferIn& buffer);
155         static void recvAddAxis(CEventServer& event);
156         void recvAddAxis(CBufferIn& buffer);
157         static void recvAddScalar(CEventServer& event);
158         void recvAddScalar(CBufferIn& buffer);
159
160         static bool dispatchEvent(CEventServer& event);
161         static void recvIndex(CEventServer& event);
162         void recvIndex(vector<int> ranks, vector<CBufferIn*> buffers);
163         void sendIndex(void);
164         void sendIndexScalarGrid();
165
166         void setContextClient(CContextClient* contextClient);
167
168         void computeDomConServer();
169         std::map<int, int> getDomConServerSide();
170         std::map<int, StdSize> getAttributesBufferSize(CContextClient* client, bool bufferForWriting = false);
171         std::map<int, StdSize> getDataBufferSize(CContextClient* client, const std::string& id = "", bool bufferForWriting = false);
172         std::vector<StdString> getDomainList();
173         std::vector<StdString> getAxisList();
174         std::vector<StdString> getScalarList();
175         std::vector<CDomain*> getDomains();
176         std::vector<CAxis*> getAxis();
177         std::vector<CScalar*> getScalars();
178         CDomain* getDomain(int domainIndex);
179         CAxis* getAxis(int axisIndex);
180         CScalar* getScalar(int scalarIndex);
181         std::vector<int> getAxisOrder();
182         std::vector<int> getGlobalDimension();
183         bool isScalarGrid() const;         
184
185         bool doGridHaveDataToWrite();
186         bool doGridHaveDataDistributed(CContextClient* client = 0);
187         size_t getWrittenDataSize() const;
188         int getNumberWrittenIndexes() const;
189         int getTotalNumberWrittenIndexes() const;
190         int getOffsetWrittenIndexes() const;
191
192         CDistributionServer* getDistributionServer();
193         CDistributionClient* getDistributionClient();
194         CGridTransformation* getTransformations();
195
196         void transformGrid(CGrid* transformGridSrc);
197         void completeGrid(CGrid* transformGridSrc = 0);
198         void doAutoDistribution(CGrid* transformGridSrc);
199         bool isTransformed();
200         void setTransformed();
201         bool isGenerated();
202         void setGenerated();
203         void addTransGridSource(CGrid* gridSrc);
204         std::map<CGrid*, std::pair<bool,StdString> >& getTransGridSource();
205         bool hasTransform();
206         size_t getGlobalWrittenSize(void) ;
207      public:
208         CArray<int, 1> storeIndex_client;
209         CArray<bool, 1> storeMask_client;
210
211/** Map containing indexes that will be sent in sendIndex(). */
212         std::map<CContextClient*, map<int, CArray<int, 1> > > storeIndex_toSrv;
213
214/** Map storing the number of senders. Key = size of receiver's intracomm */
215         std::map<int, std::map<int,int> > nbSenders;
216
217         std::map<CContextClient*, std::map<int,int> > nbReadSenders;
218
219         map<int, CArray<int, 1> > storeIndex_fromSrv; // Support, for now, reading with level-1 server
220
221         map<int, CArray<size_t, 1> > outIndexFromClient;  // Deprecated
222
223         map<int, CArray<size_t, 1> > compressedOutIndexFromClient;
224
225/** Map storing received indexes. Key = sender rank, value = index array. */
226         map<int, CArray<size_t, 1> > outGlobalIndexFromClient;
227
228// Manh Ha's comment: " A client receives global index from other clients (via recvIndex)
229// then does mapping these index into local index of STORE_CLIENTINDEX
230// In this way, store_clientIndex can be used as an input of a source filter
231// Maybe we need a flag to determine whether a client wants to write. TODO "
232
233/** Map storing received data. Key = sender rank, value = data array.
234 *  The map is created in CGrid::computeClientIndex and filled upon receiving data in CField::recvUpdateData() */
235         map<int, CArray<size_t, 1> > outLocalIndexStoreOnClient; 
236
237/** Indexes calculated based on server-like distribution.
238 *  They are used for writing/reading data and only calculated for server level that does the writing/reading.
239 *  Along with localIndexToWriteOnClient, these indexes are used to correctly place incoming data. */
240         CArray<size_t,1> localIndexToWriteOnServer;
241
242/** Indexes calculated based on client-like distribution.
243 *  They are used for writing/reading data and only calculated for server level that does the writing/reading.
244 *  Along with localIndexToWriteOnServer, these indexes are used to correctly place incoming data. */
245         CArray<size_t,1> localIndexToWriteOnClient;
246
247         CArray<size_t,1> indexFromClients;
248
249         bool hasMask(void) const;
250         void checkMask(void);
251         void createMask(void);
252         void modifyMask(const CArray<int,1>& indexToModify, bool valueToModify = false);
253         void modifyMaskSize(const std::vector<int>& newDimensionSize, bool newValue = false);
254
255         void computeGridGlobalDimension(const std::vector<CDomain*>& domains,
256                                         const std::vector<CAxis*>& axis,
257                                         const std::vector<CScalar*>& scalars,
258                                         const CArray<int,1>& axisDomainOrder);
259
260      private:
261       template<int N>
262       void checkGridMask(CArray<bool,N>& gridMask,
263                          const std::vector<CArray<bool,1>* >& domainMasks,
264                          const std::vector<CArray<bool,1>* >& axisMasks,
265                          const CArray<int,1>& axisDomainOrder,
266                          bool createMask = false);
267        template<int N>
268        void modifyGridMask(CArray<bool,N>& gridMask, const CArray<int,1>& indexToModify, bool valueToModify);
269
270        template<int N>
271        void modifyGridMaskSize(CArray<bool,N>& gridMask, const std::vector<int>& eachDimSize, bool newValue);
272
273        void storeField_arr(const double* const data, CArray<double, 1>& stored) const;
274        void restoreField_arr(const CArray<double, 1>& stored, double* const data) const;
275        void uncompressField_arr(const double* const data, CArray<double, 1>& outData) const;
276        void maskField_arr(const double* const data, CArray<double, 1>& stored) const;
277
278        void setVirtualDomainGroup(CDomainGroup* newVDomainGroup);
279        void setVirtualAxisGroup(CAxisGroup* newVAxisGroup);
280        void setVirtualScalarGroup(CScalarGroup* newVScalarGroup);
281
282        void setDomainList(const std::vector<CDomain*> domains = std::vector<CDomain*>());
283        void setAxisList(const std::vector<CAxis*> axis = std::vector<CAxis*>());
284        void setScalarList(const std::vector<CScalar*> scalars = std::vector<CScalar*>());
285
286        CDomainGroup* getVirtualDomainGroup() const;
287        CAxisGroup* getVirtualAxisGroup() const;
288        CScalarGroup* getVirtualScalarGroup() const;
289
290        void checkAttributesAfterTransformation();
291        void setTransformationAlgorithms();
292        void computeIndexByElement(const std::vector<std::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
293                                   const CContextClient* client,
294                                   CClientServerMapping::GlobalIndexMap& globalIndexOnServer);
295        int computeGridGlobalDimension(std::vector<int>& globalDim,
296                                       const std::vector<CDomain*> domains,
297                                       const std::vector<CAxis*> axis,
298                                       const std::vector<CScalar*> scalars,
299                                       const CArray<int,1>& axisDomainOrder);
300        int getDistributedDimension();
301
302        void computeClientIndex();
303        void computeConnectedClients();
304        void computeClientIndexScalarGrid(); 
305        void computeConnectedClientsScalarGrid(); 
306
307      private:
308
309/** Clients that have to send a grid. There can be multiple clients in case of secondary server, otherwise only one client. */
310        std::list<CContextClient*> clients;
311        std::set<CContextClient*> clientsSet;
312
313        bool isChecked;
314        bool isDomainAxisChecked;
315        bool isIndexSent;
316
317        CDomainGroup* vDomainGroup_;
318        CAxisGroup* vAxisGroup_;
319        CScalarGroup* vScalarGroup_;
320        std::vector<std::string> axisList_, domList_, scalarList_;
321        bool isAxisListSet, isDomListSet, isScalarListSet;
322
323/** Client-like distribution calculated based on the knowledge of the entire grid */
324        CDistributionClient* clientDistribution_;
325
326/** Server-like distribution calculated upon receiving indexes */
327        CDistributionServer* serverDistribution_;
328
329        CClientServerMapping* clientServerMap_;
330        size_t writtenDataSize_;
331        int numberWrittenIndexes_, totalNumberWrittenIndexes_, offsetWrittenIndexes_;
332
333/** Map storing local ranks of connected receivers. Key = size of receiver's intracomm.
334  * It is calculated in computeConnectedClients(). */
335        std::map<int, std::vector<int> > connectedServerRank_;
336
337/** Map storing the size of data to be send. Key = size of receiver's intracomm
338  * It is calculated in computeConnectedClients(). */
339        std::map<int, std::map<int,size_t> > connectedDataSize_;
340
341/** Ranks of connected receivers in case of reading. It is calculated in recvIndex(). */
342        std::vector<int> connectedServerRankRead_;
343
344/** Size of data to be send in case of reading. It is calculated in recvIndex(). */
345        std::map<int,size_t> connectedDataSizeRead_;
346
347        bool isDataDistributed_;       
348         //! True if and only if the data defined on the grid can be outputted in a compressed way
349        bool isCompressible_;
350        std::set<std::string> relFilesCompressed;
351
352        bool isTransformed_, isGenerated_;
353        bool computedWrittenIndex_;
354        std::vector<int> axisPositionInGrid_;
355        CGridTransformation* transformations_;
356        bool hasDomainAxisBaseRef_;       
357        std::map<CGrid*, std::pair<bool,StdString> > gridSrc_;
358        bool hasTransform_;
359
360/** Map storing global indexes of server-like (band-wise) distribution for sending to receivers.
361  * Key = size of receiver's intracomm.
362  */
363//        std::map<CContextClient*, CClientServerMapping::GlobalIndexMap> globalIndexOnServer_;
364        std::map<int, CClientServerMapping::GlobalIndexMap> globalIndexOnServer_;
365
366
367/** List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false) */
368        std::vector<int> order_;
369
370   }; // class CGrid
371
372   ///--------------------------------------------------------------
373
374   template <int n>
375   void CGrid::inputField(const CArray<double,n>& field, CArray<double,1>& stored) const
376   TRY
377   {
378//#ifdef __XIOS_DEBUG
379      if (this->getDataSize() != field.numElements())
380         ERROR("void CGrid::inputField(const  CArray<double,n>& field, CArray<double,1>& stored) const",
381                << "[ Awaiting data of size = " << this->getDataSize() << ", "
382                << "Received data size = "      << field.numElements() << " ] "
383                << "The data array does not have the right size! "
384                << "Grid = " << this->getId())
385//#endif
386      this->storeField_arr(field.dataFirst(), stored);
387   }
388   CATCH
389
390   template <int n>
391   void CGrid::maskField(const CArray<double,n>& field, CArray<double,1>& stored) const
392   {
393//#ifdef __XIOS_DEBUG
394      if (this->getDataSize() != field.numElements())
395         ERROR("void CGrid::inputField(const  CArray<double,n>& field, CArray<double,1>& stored) const",
396                << "[ Awaiting data of size = " << this->getDataSize() << ", "
397                << "Received data size = "      << field.numElements() << " ] "
398                << "The data array does not have the right size! "
399                << "Grid = " << this->getId())
400//#endif
401      this->maskField_arr(field.dataFirst(), stored);
402   }
403
404   template <int n>
405   void CGrid::outputField(const CArray<double,1>& stored, CArray<double,n>& field) const
406   TRY
407   {
408//#ifdef __XIOS_DEBUG
409      if (this->getDataSize() != field.numElements())
410         ERROR("void CGrid::outputField(const CArray<double,1>& stored, CArray<double,n>& field) const",
411                << "[ Size of the data = " << this->getDataSize() << ", "
412                << "Output data size = "   << field.numElements() << " ] "
413                << "The ouput array does not have the right size! "
414                << "Grid = " << this->getId())
415//#endif
416      this->restoreField_arr(stored, field.dataFirst());
417   }
418   CATCH
419
420   /*!
421     This function removes the effect of mask on received data on the server.
422     This function only serve for the checking purpose. TODO: Something must be done to seperate mask and data_index from each other in received data
423     \data data received data with masking effect on the server
424     \outData data without masking effect
425   */
426   template <int N>
427   void CGrid::uncompressField(const CArray<double,N>& data, CArray<double,1>& outData) const
428   TRY
429   {     
430     uncompressField_arr(data.dataFirst(), outData);
431   }
432   CATCH
433
434   template<int N>
435   void CGrid::checkGridMask(CArray<bool,N>& gridMask,
436                             const std::vector<CArray<bool,1>* >& domainMasks,
437                             const std::vector<CArray<bool,1>* >& axisMasks,
438                             const CArray<int,1>& axisDomainOrder,
439                             bool createMask)
440   TRY
441   {
442     int idx = 0;
443     int numElement = axisDomainOrder.numElements();
444     int dim = domainMasks.size() * 2 + axisMasks.size();
445     std::vector<CDomain*> domainP = this->getDomains();
446     std::vector<CAxis*> axisP = this->getAxis();
447
448     std::vector<int> idxLoop(dim,0), indexMap(numElement), eachDimSize(dim);
449     std::vector<int> currentIndex(dim);
450     int idxDomain = 0, idxAxis = 0;
451    for (int i = 0; i < numElement; ++i)
452    {
453      indexMap[i] = idx;
454      if (2 == axisDomainOrder(i)) {
455          eachDimSize[indexMap[i]]   = domainP[idxDomain]->ni;
456          eachDimSize[indexMap[i]+1] = domainP[idxDomain]->nj;
457          idx += 2; ++idxDomain;
458      }
459      else if (1 == axisDomainOrder(i)) {
460//        eachDimSize[indexMap[i]] = axisMasks[idxAxis]->numElements();
461        eachDimSize[indexMap[i]] = axisP[idxAxis]->n;
462        ++idx; ++idxAxis;
463      }
464      else {};
465    }
466
467    if (!gridMask.isEmpty() && !createMask)
468    {
469      for (int i = 0; i < dim; ++i)
470      {
471        if (gridMask.extent(i) != eachDimSize[i])
472          ERROR("CGrid::checkMask(void)",
473                << "The mask has one dimension whose size is different from the one of the local grid." << std::endl
474                << "Local size of dimension " << i << " is " << eachDimSize[i] << "." << std::endl
475                << "Mask size for dimension " << i << " is " << gridMask.extent(i) << "." << std::endl
476                << "Grid = " << this->getId())
477      }
478    }
479    else {
480        CArrayBoolTraits<CArray<bool,N> >::resizeArray(gridMask,eachDimSize);
481        gridMask = true;
482    }
483
484    int ssize = gridMask.numElements();
485    idx = 0;
486    while (idx < ssize)
487    {
488      for (int i = 0; i < dim-1; ++i)
489      {
490        if (idxLoop[i] == eachDimSize[i])
491        {
492          idxLoop[i] = 0;
493          ++idxLoop[i+1];
494        }
495      }
496
497      // Find out outer index
498      idxDomain = idxAxis = 0;
499      bool maskValue = true;
500      for (int i = 0; i < numElement; ++i)
501      {
502        if (2 == axisDomainOrder(i))
503        {
504          int idxTmp = idxLoop[indexMap[i]] + idxLoop[indexMap[i]+1] * eachDimSize[indexMap[i]];
505          if (idxTmp < (*domainMasks[idxDomain]).numElements())
506            maskValue = maskValue && (*domainMasks[idxDomain])(idxTmp);
507          else
508            maskValue = false;
509          ++idxDomain;
510        }
511        else if (1 == axisDomainOrder(i))
512        {
513          int idxTmp = idxLoop[indexMap[i]];
514          if (idxTmp < (*axisMasks[idxAxis]).numElements())
515            maskValue = maskValue && (*axisMasks[idxAxis])(idxTmp);
516          else
517            maskValue = false;
518
519          ++idxAxis;
520        }
521      }
522
523      int maskIndex = idxLoop[0];
524      int mulDim = 1;
525      for (int k = 1; k < dim; ++k)
526      {
527        mulDim *= eachDimSize[k-1];
528        maskIndex += idxLoop[k]*mulDim;
529      }
530      *(gridMask.dataFirst()+maskIndex) &= maskValue;
531
532      ++idxLoop[0];
533      ++idx;
534    }
535   }
536   CATCH_DUMP_ATTR
537
538   template<int N>
539   void CGrid::modifyGridMaskSize(CArray<bool,N>& gridMask,
540                                  const std::vector<int>& eachDimSize,
541                                  bool newValue)
542   TRY
543   {
544      if (N != eachDimSize.size())
545      {
546        // ERROR("CGrid::modifyGridMaskSize(CArray<bool,N>& gridMask,
547        //                                  const std::vector<int>& eachDimSize,
548        //                                  bool newValue)",
549        //       << "Dimension size of the mask is different from input dimension size." << std::endl
550        //       << "Mask dimension is " << N << "." << std::endl
551        //       << "Input dimension is " << eachDimSize.size() << "." << std::endl
552        //       << "Grid = " << this->getId())
553      }
554      CArrayBoolTraits<CArray<bool,N> >::resizeArray(gridMask,eachDimSize);
555      gridMask = newValue;
556   }
557   CATCH_DUMP_ATTR
558                                 
559
560   /*!
561     Modify the current mask of grid, the local index to be modified will take value false
562     \param [in/out] gridMask current mask of grid
563     \param [in] indexToModify local index to modify
564   */
565   template<int N>
566   void CGrid::modifyGridMask(CArray<bool,N>& gridMask, const CArray<int,1>& indexToModify, bool valueToModify)
567   TRY
568   {     
569     int num = indexToModify.numElements();
570     for (int idx = 0; idx < num; ++idx)
571     {
572       *(gridMask.dataFirst()+indexToModify(idx)) = valueToModify;
573     }
574   }
575   CATCH_DUMP_ATTR
576
577   ///--------------------------------------------------------------
578
579
580
581   // Declare/Define CGridGroup and CGridDefinition
582   DECLARE_GROUP(CGrid);
583
584   ///--------------------------------------------------------------
585
586} // namespace xios
587
588#endif // __XIOS_CGrid__
Note: See TracBrowser for help on using the repository browser.