1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
//-------------------------------------------------------------------------
// Filename      : NCHelper.hpp
//
// Purpose       : Climate NC file helper
//
// Creator       : Danqing Wu
//-------------------------------------------------------------------------

#ifndef NCHELPER_HPP
#define NCHELPER_HPP

#include "ReadNC.hpp"

#ifdef WIN32
#ifdef size_t
#undef size_t
#endif
#endif

namespace moab
{

//! Helper class to isolate reading of several different nc file formats
class NCHelper
{
  public:
    NCHelper( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet )
        : _readNC( readNC ), _fileId( fileId ), _opts( opts ), _fileSet( fileSet ), nTimeSteps( 0 ), nLevels( 1 ),
          tDim( -1 ), levDim( -1 )
    {
    }
    virtual ~NCHelper() {}

    //! Get appropriate helper instance for ReadNC class
    static NCHelper* get_nc_helper( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet );

    //! Interfaces to be implemented in child classes
    virtual ErrorCode init_mesh_vals()                                                                        = 0;
    virtual ErrorCode check_existing_mesh()                                                                   = 0;<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class
    virtual ErrorCode create_mesh( Range& faces )                                                             = 0;<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class
    virtual ErrorCode read_variables( std::vector< std::string >& var_names, std::vector< int >& tstep_nums ) = 0;<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class<--- Virtual function in base class
    virtual std::string get_mesh_type_name()                                                                  = 0;

    //! Create NC conventional tags
    ErrorCode create_conventional_tags( const std::vector< int >& tstep_nums );

    //! Update time tag values if timesteps spread across files
    ErrorCode update_time_tag_vals();

    // An object to hold vertex coordinates, and an operator
    // for storing them in a STL tree-based container. use a tolerance saved somewhere as 1.e-12
    class Node3D
    {
      public:
        double coords[3];
        bool operator<( const Node3D& ) const;
        Node3D( double x, double y, double z )
        {
            coords[0] = x;
            coords[1] = y;
            coords[2] = z;
        }
    };

  protected:
    //! Separate set and non-set variables (common to scd mesh and ucd mesh)
    ErrorCode read_variables_setup( std::vector< std::string >& var_names,
                                    std::vector< int >& tstep_nums,
                                    std::vector< ReadNC::VarData >& vdatas,
                                    std::vector< ReadNC::VarData >& vsetdatas );

    //! Read set variables (common to scd mesh and ucd mesh)
    ErrorCode read_variables_to_set( std::vector< ReadNC::VarData >& vdatas, std::vector< int >& tstep_nums );

    ErrorCode read_coordinate( const char* var_name, int lmin, int lmax, std::vector< double >& cvals );

    ErrorCode get_tag_to_set( ReadNC::VarData& var_data, int tstep_num, Tag& tagh );

    ErrorCode get_tag_to_nonset( ReadNC::VarData& var_data, int tstep_num, Tag& tagh, int num_lev );

    //! Create a character string attString of attMap. with '\0'
    //! terminating each attribute name, ';' separating the data type
    //! and value, and ';' separating one name/data type/value from
    //! the next'. attLen stores the end position for each name/data
    //! type/ value.
    ErrorCode create_attrib_string( const std::map< std::string, ReadNC::AttData >& attMap,
                                    std::string& attString,
                                    std::vector< int >& attLen );

    //! For a dimension that does not have a corresponding coordinate variable (e.g. ncol for
    //! HOMME), create a dummy variable with a sparse tag to store the dimension length
    ErrorCode create_dummy_variables();

  private:
    //! Used by read_variables_to_set()
    ErrorCode read_variables_to_set_allocate( std::vector< ReadNC::VarData >& vdatas, std::vector< int >& tstep_nums );

  protected:
    //! Allow NCHelper to directly access members of ReadNC
    ReadNC* _readNC;

    //! Cache some information from ReadNC
    int _fileId;
    const FileOptions& _opts;
    EntityHandle _fileSet;

    //! Dimensions of time and level
    int nTimeSteps, nLevels;

    //! Values for time and level
    std::vector< double > tVals, levVals;

    //! Dimension numbers for time and level
    int tDim, levDim;

    //! Ignored variables
    std::set< std::string > ignoredVarNames;

    //! Dummy variables
    std::set< std::string > dummyVarNames;
};

//! Child helper class for scd mesh, e.g. CAM_EL or CAM_FV
class ScdNCHelper : public NCHelper
{
  public:
    ScdNCHelper( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet )
        : NCHelper( readNC, fileId, opts, fileSet ), iDim( -1 ), jDim( -1 ), iCDim( -1 ), jCDim( -1 )
    {
        for( unsigned int i = 0; i < 6; i++ )
        {
            gDims[i]  = -1;
            lDims[i]  = -1;
            gCDims[i] = -1;
            lCDims[i] = -1;
        }

        locallyPeriodic[0] = locallyPeriodic[1] = locallyPeriodic[2] = 0;
        globallyPeriodic[0] = globallyPeriodic[1] = globallyPeriodic[2] = 0;
    }
    virtual ~ScdNCHelper() {}

  private:
    //! Implementation of NCHelper::check_existing_mesh()
    virtual ErrorCode check_existing_mesh();<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class
    //! Implementation of NCHelper::create_mesh()
    virtual ErrorCode create_mesh( Range& faces );<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class
    //! Implementation of NCHelper::read_variables()
    virtual ErrorCode read_variables( std::vector< std::string >& var_names, std::vector< int >& tstep_nums );<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class

    //! Read non-set variables for scd mesh
    ErrorCode read_scd_variables_to_nonset_allocate( std::vector< ReadNC::VarData >& vdatas,
                                                     std::vector< int >& tstep_nums );
    ErrorCode read_scd_variables_to_nonset( std::vector< ReadNC::VarData >& vdatas, std::vector< int >& tstep_nums );

    //! Create COORDS tag for quads coordinate
    ErrorCode create_quad_coordinate_tag();

    template < typename T >
    void kji_to_jik( size_t ni, size_t nj, size_t nk, void* dest, T* source )
    {
        size_t nik = ni * nk, nij = ni * nj;
        T* tmp_data = reinterpret_cast< T* >( dest );
        for( std::size_t j = 0; j != nj; j++ )
            for( std::size_t i = 0; i != ni; i++ )
                for( std::size_t k = 0; k != nk; k++ )
                    tmp_data[j * nik + i * nk + k] = source[k * nij + j * ni + i];
    }

  protected:
    //! Dimensions of global grid in file
    int gDims[6];

    //! Dimensions of my local part of grid
    int lDims[6];

    //! Center dimensions of global grid in file
    int gCDims[6];

    //! Center dimensions of my local part of grid
    int lCDims[6];

    //! Values for i/j
    std::vector< double > ilVals, jlVals;

    //! Center values for i/j
    std::vector< double > ilCVals, jlCVals;

    //! Dimension numbers for i/j
    int iDim, jDim;

    //! Center dimension numbers for i/j
    int iCDim, jCDim;

    //! Whether mesh is locally periodic in i or j or k
    int locallyPeriodic[3];

    //! Whether mesh is globally periodic in i or j or k
    int globallyPeriodic[3];
};

//! Child helper class for ucd mesh, e.g. CAM_SE (HOMME) or MPAS
class UcdNCHelper : public NCHelper
{
  public:
    UcdNCHelper( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet )
        : NCHelper( readNC, fileId, opts, fileSet ), nCells( 0 ), nEdges( 0 ), nVertices( 0 ), nLocalCells( 0 ),
          nLocalEdges( 0 ), nLocalVertices( 0 ), cDim( -1 ), eDim( -1 ), vDim( -1 )
    {
    }
    virtual ~UcdNCHelper() {}

  private:
    //! Implementation of NCHelper::read_variables()
    virtual ErrorCode read_variables( std::vector< std::string >& var_names, std::vector< int >& tstep_nums );<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class<--- Function in derived class

    //! Read non-set variables for ucd mesh (implemented differently in child classes)
    virtual ErrorCode read_ucd_variables_to_nonset_allocate( std::vector< ReadNC::VarData >& vdatas,
                                                             std::vector< int >& tstep_nums ) = 0;
#ifdef MOAB_HAVE_PNETCDF
    virtual ErrorCode read_ucd_variables_to_nonset_async( std::vector< ReadNC::VarData >& vdatas,
                                                          std::vector< int >& tstep_nums ) = 0;
#else
    virtual ErrorCode read_ucd_variables_to_nonset( std::vector< ReadNC::VarData >& vdatas,
                                                    std::vector< int >& tstep_nums ) = 0;
#endif

  protected:
    //! This version takes as input the moab range, from which we actually need just the
    //! size of each sequence, for a proper transpose of the data
    template < typename T >
    void kji_to_jik_stride( size_t, size_t nj, size_t nk, void* dest, T* source, Range& localGid )
    {
        std::size_t idxInSource = 0;  // Position of the start of the stride
        // For each subrange, we will transpose a matrix of size
        // subrange*nj*nk (subrange takes the role of ni)
        T* tmp_data = reinterpret_cast< T* >( dest );
        for( Range::pair_iterator pair_iter = localGid.pair_begin(); pair_iter != localGid.pair_end(); ++pair_iter )
        {
            std::size_t size_range = pair_iter->second - pair_iter->first + 1;
            std::size_t nik = size_range * nk, nij = size_range * nj;
            for( std::size_t j = 0; j != nj; j++ )
                for( std::size_t i = 0; i != size_range; i++ )
                    for( std::size_t k = 0; k != nk; k++ )
                        tmp_data[idxInSource + j * nik + i * nk + k] =
                            source[idxInSource + k * nij + j * size_range + i];
            idxInSource += ( size_range * nj * nk );
        }
    }

    //! Dimensions of global grid in file
    int nCells;
    int nEdges;
    int nVertices;

    //! Dimensions of my local part of grid
    int nLocalCells;
    int nLocalEdges;
    int nLocalVertices;

    //! Coordinate values for vertices
    std::vector< double > xVertVals, yVertVals, zVertVals;

    //! Dimension numbers for nCells, nEdges and nVertices
    int cDim, eDim, vDim;

    //! Local global ID for cells, edges and vertices
    Range localGidCells, localGidEdges, localGidVerts;
};

}  // namespace moab

#endif