Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
WriteNC.hpp
Go to the documentation of this file.
1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation. Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 #ifndef WRITENC_HPP_
17 #define WRITENC_HPP_
18 
19 #ifndef IS_BUILDING_MB
20 #error "WriteNC.hpp isn't supposed to be included into an application"
21 #endif
22 
23 #include <vector>
24 #include <map>
25 #include <set>
26 #include <string>
27 
28 #include "moab/WriterIface.hpp"
29 #include "moab/ScdInterface.hpp"
30 #include "DebugOutput.hpp"
31 
32 #ifdef MOAB_HAVE_MPI
33 #include "moab_mpi.h"
34 #include "moab/ParallelComm.hpp"
35 #endif
36 
37 // Runtime dispatch — same rationale as ReadNC.hpp; see MBNcDispatch.hpp.
38 // The NCFUNC* macros below now route puts through mbnc_put_* wrappers
39 // (which select PNetCDF collective or standard NetCDF at runtime per the
40 // backend tag of the fileId returned by WriteNC's open/create path).
41 #include "MBNcDispatch.hpp"
42 
43 //! Generic NC function dispatch
44 #define NCFUNC( func ) mbnc_##func
45 
46 //! Collective I/O mode put (PNetCDF: collective; others: only mode)
47 #define NCFUNCAP( func ) mbnc_put##func
48 
49 //! Independent I/O mode put. Routes to ncmpi_put_vara_* (no _all) on
50 //! PNetCDF; on non-PNetCDF backends maps to the same nc_put_vara_*
51 //! call as the collective variant. Caller is still responsible for
52 //! mbnc_begin_indep_data / mbnc_end_indep_data brackets when running
53 //! on PNetCDF (those are no-ops on other backends).
54 #define NCFUNCP( func ) mbnc_put##func##_indep
55 
56 //! Nonblocking put (PNetCDF request aggregation; blocking on others)
57 #define NCFUNCREQP( func ) mbnc_iput##func
58 
59 #define NCDF_SIZE size_t
60 #define NCDF_DIFF ptrdiff_t
61 
62 namespace moab
63 {
64 
65 class WriteUtilIface;
66 class NCWriteHelper;
67 
68 /**
69  * \brief Export NC files.
70  */
71 class WriteNC : public WriterIface
72 {
73  friend class NCWriteHelper;
74  friend class ScdNCWriteHelper;
75  friend class UcdNCWriteHelper;
76  friend class NCWriteEuler;
77  friend class NCWriteFV;
78  friend class NCWriteHOMME;
79  friend class NCWriteMPAS;
80  friend class NCWriteGCRM;
81  friend class NCWriteScrip;
82  friend class NCWriteESMF;
83  friend class NCWriteDomain;
84 
85  public:
86  //! Factory method
87  static WriterIface* factory( Interface* );
88 
89  //! Constructor
90  explicit WriteNC( Interface* impl = NULL );
91 
92  //! Destructor
93  virtual ~WriteNC();
94 
95  //! Writes out a file
96  ErrorCode write_file( const char* file_name,
97  const bool overwrite,
98  const FileOptions& opts,
99  const EntityHandle* output_list,
100  const int num_sets,
101  const std::vector< std::string >& qa_list,
102  const Tag* tag_list = NULL,
103  int num_tags = 0,
104  int export_dimension = 3 );
105 
106  private:
107  //! ENTLOCNSEDGE for north/south edge
108  //! ENTLOCWEEDGE for west/east edge
110  {
118  };
119 
120  class AttData
121  {
122  public:
123  AttData() : attId( -1 ), attLen( 0 ), attVarId( -2 ), attDataType( NC_NAT ) {}
124  int attId;
126  int attVarId;
127  nc_type attDataType;
128  std::string attValue;
129  };
130 
131  class VarData
132  {
133  public:
134  VarData() : varId( -1 ), numAtts( -1 ), entLoc( ENTLOCSET ), numLev( 0 ), sz( 0 ), has_tsteps( false ) {}
135  int varId;
136  int numAtts;
137  nc_type varDataType;
138  std::vector< int > varDims; // The dimension indices making up this multi-dimensional variable
139  std::map< std::string, AttData > varAtts;
140  std::string varName;
141  std::vector< Tag > varTags; // Tags created for this variable, e.g. one tag per timestep
142  std::vector< void* > memoryHogs; // These will point to the real data; fill before writing the data
143  std::vector< NCDF_SIZE > writeStarts; // Starting index for writing data values along each dimension
144  std::vector< NCDF_SIZE > writeCounts; // Number of data values to be written along each dimension
145  int entLoc;
146  int numLev;
147  int sz;
148  bool has_tsteps; // Indicate whether timestep numbers are appended to tag names
149  };
150 
151  //! This info will be reconstructed from metadata stored on conventional fileSet tags
152  //! Dimension names
153  std::vector< std::string > dimNames;
154 
155  //! Dimension lengths
156  std::vector< int > dimLens;
157 
158  //! Will collect used dimensions (coordinate variables)
159  std::set< std::string > usedCoordinates;
160 
161  //! Dummy variables (for dimensions that have no corresponding coordinate variables)
162  std::set< std::string > dummyVarNames;
163 
164  //! Global attribs
165  std::map< std::string, AttData > globalAtts;
166 
167  //! Variable info
168  std::map< std::string, VarData > varInfo;
169 
170  ErrorCode parse_options( const FileOptions& opts,
171  std::vector< std::string >& var_names,
172  std::vector< std::string >& desired_names,
173  std::vector< int >& tstep_nums,
174  std::vector< double >& tstep_vals );
175  /*
176  * Map out the header, from tags on file set; it is the inverse process from
177  * ErrorCode NCHelper::create_conventional_tags
178  */
180 
181  ErrorCode process_concatenated_attribute( const void* attPtr,
182  int attSz,
183  std::vector< int >& attLen,
184  std::map< std::string, AttData >& attributes );
185 
186  //! Interface instance
189 
190  //! File var
191  const char* fileName;
192 
193  //! File numbers assigned by (p)netcdf
194  int fileId;
195 
196  //! Debug stuff
198 
199 #ifdef MOAB_HAVE_MPI
200  ParallelComm* myPcomm;
201 #endif
202 
203  //! Write options
204  bool noMesh;
205  bool noVars;
206  bool append;
207 
208  //! Cached tags for writing. This will be important for ordering the data, in parallel
210 
211  //! Are we writing in parallel? (probably in the future)
213 
214  //! CAM Euler, etc,
215  std::string grid_type;
216 
217  //! Helper class instance
219 };
220 
221 } // namespace moab
222 
223 #endif