RBGen  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
RBGen_NetCDFFileIOHandler.cpp
1 #include "RBGen_NetCDFFileIOHandler.h"
2 
3 #include "Epetra_BLAS.h"
4 #include "Epetra_Export.h"
5 #include "Epetra_Import.h"
6 #include "Epetra_Map.h"
7 #include "Epetra_Vector.h"
8 #include "Epetra_MultiVector.h"
9 
10 #include "Teuchos_Utils.hpp"
11 #include "Teuchos_Assert.hpp"
12 
13 #ifdef EPETRA_MPI
14 #include "Epetra_MpiComm.h"
15 #else
16 #include "Epetra_SerialComm.h"
17 #endif
18 
19 #include "Teuchos_RCP.hpp"
21 
22 namespace RBGen {
23 
25  : isInit(false), num_nodes(0), num_nod_var(0), len_string(0), var_name(0)
26  {
27  }
28 
30  {
31  for (int i=0; i<num_nod_var; i++)
32  delete [] var_name[i];
33  if (var_name) delete [] var_name;
34  }
35 
37  {
38 
39  // Save the parameter list.
40  params_ = params;
41 
42  // Get the "File I/O" sublist.
43  const Teuchos::ParameterList& fileio_params = params->sublist( "File IO" );
44 
45  // Get the input path.
46  in_path = "";
47  if ( fileio_params.isParameter( "Data Input Path" ) ) {
48  in_path = Teuchos::getParameter<std::string>( fileio_params, "Data Input Path" );
49  }
50 
51  // Get the output path.
52  out_path = "";
53  if ( fileio_params.isParameter( "Data Output Path" ) ) {
54  out_path = Teuchos::getParameter<std::string>( fileio_params, "Data Output Path" );
55  }
56 
57  // This file i/o handler is now initialized.
58  isInit = true;
59  }
60 
61  Teuchos::RCP<Epetra_MultiVector> NetCDFFileIOHandler::Read( const std::vector<std::string>& filenames )
62  {
63 #ifdef EPETRA_MPI
64  Epetra_MpiComm comm( MPI_COMM_WORLD );
65 #else
66  Epetra_SerialComm comm;
67 #endif
68 
69  int ncid=0, row_id=0, col_id=0, ss_id=0, num_nod_var_id=0;
70  int i, j, k, col_ptr=0;
71  int rows=0, num_ss=0, num_vars=0, status=0;
72  size_t rows_t=0, num_nod_var_t=0, start2[2],count2[2];
73  //
74  // Check to see if we have to create a scaling index vector
75  //
76  bool createSSIdx = false;
77  std::vector< std::pair<int,int> > scaling_idx;
78  std::pair<int, int> idx_pair;
79  /*
80  try {
81  scaling_idx = Teuchos::getParameter< std::vector< std::pair<int,int> > >( *params_, "Snapshot Scaling Indices" );
82  }
83  catch (std::exception &e) {
84  createSSIdx = true;
85  }
86  */
87  //
88  // Open all the files and check that the snapshots have the same dimensions.
89  //
90  if ( comm.MyPID() == 0 ) {
91  size_t rows0=0, cols0=0, cols_t=0, total_rows=0;
92 
93  std::string temp_filename = in_path + filenames[0];
94  status = nc_open(temp_filename.c_str(),NC_NOWRITE,&ncid);
95  if (status != NC_NOERR) handle_error(status);
96  //
97  // If the scaling index vector is needed we can create it here.
98  //
99  if (createSSIdx) {
100  idx_pair.first = total_rows;
101  }
102  //
103  // Get information on the number of snapshots in the file.
104  status = nc_inq_dimid(ncid,"row",&row_id);
105  if (status != NC_NOERR) handle_error(status);
106  status = nc_inq_dimlen(ncid,row_id, &rows0);
107  if (status != NC_NOERR) handle_error(status);
108  total_rows += rows0;
109  //
110  // Get information on the snapshot length.
111  status = nc_inq_dimid(ncid,"col",&col_id);
112  if (status != NC_NOERR) handle_error(status);
113  status = nc_inq_dimlen(ncid,col_id, &cols0);
114  if (status != NC_NOERR) handle_error(status);
115  //
116  if (!isInit) {
117  int len_string_id, num_nodes_id, name_nod_var_id;
118  size_t len_string_t, num_nodes_t;
119 
120  // Get maximum variable name length.
121  status=nc_inq_dimid(ncid,"len_string",&len_string_id);
122  if (status != NC_NOERR) handle_error(status);
123  status=nc_inq_dimlen(ncid,len_string_id,&len_string_t);
124  if (status != NC_NOERR) handle_error(status);
125 
126  // Get number of nodes.
127  status=nc_inq_dimid(ncid,"num_nodes",&num_nodes_id);
128  if (status != NC_NOERR) handle_error(status);
129  status=nc_inq_dimlen(ncid,num_nodes_id, &num_nodes_t);
130  if (status != NC_NOERR) handle_error(status);
131 
132  // Get number of nodal variables.
133  status=nc_inq_dimid(ncid,"num_nod_var",&num_nod_var_id);
134  if (status != NC_NOERR) handle_error(status);
135  status=nc_inq_dimlen(ncid,num_nod_var_id,&num_nod_var_t);
136  if (status != NC_NOERR) handle_error(status);
137 
138  len_string = len_string_t;
139  num_nodes = num_nodes_t;
140  num_nod_var = num_nod_var_t;
141 
142  // Read in names of nodal variables.
143  status=nc_inq_varid(ncid,"name_nod_var",&name_nod_var_id);
144  if (status != NC_NOERR) handle_error(status);
145 
146  var_name = new char*[ num_nod_var ];
147  for (i=0; i<num_nod_var; ++i)
148  var_name[i] = new char[ len_string ];
149 
150  for (i=0; i<num_nod_var; ++i) {
151  start2[0]=i;
152  start2[1]=0;
153  count2[0]=1;
154  count2[1]=len_string;
155 
156  status=nc_get_vara_text(ncid,name_nod_var_id,start2,count2,var_name[i]);
157  if (status != NC_NOERR) handle_error(status);
158  }
159  //
160  // If the scaling index vector is needed we can set the endpoint here.
161  //
162  if (createSSIdx) {
163  idx_pair.second = total_rows-1;
164  scaling_idx.push_back( idx_pair );
165  }
166 
167  // Now we are initialized!
168  isInit = true;
169 
170  // Output information.
171  std::cout<<"len_string = "<<len_string<<std::endl;
172  std::cout<<"num_nodes = "<<num_nodes<<std::endl;
173  std::cout<<"num_nod_var = "<<num_nod_var<<std::endl;
174  std::cout<<"var_name = ";
175  for (i=0; i< num_nod_var; ++i)
176  std::cout<<var_name[i]<<" ";
177  std::cout<<std::endl;
178  }
179 
180  // Close first file.
181  status = nc_close(ncid);
182  if (status != NC_NOERR) handle_error(status);
183  //
184  for (i=1; i<(int)filenames.size(); i++) {
185  std::string temp_filename = in_path + filenames[i];
186  status = nc_open(temp_filename.c_str(),NC_NOWRITE,&ncid);
187  if (status != NC_NOERR) handle_error(status);
188  //
189  // If the scaling index vector is needed we can create it here.
190  //
191  if (createSSIdx) {
192  idx_pair.first = total_rows;
193  }
194  //
195  // Get information on the number of snapshots in the file.
196  status = nc_inq_dimid(ncid,"row",&row_id);
197  if (status != NC_NOERR) handle_error(status);
198  status = nc_inq_dimlen(ncid,row_id, &rows_t);
199  if (status != NC_NOERR) handle_error(status);
200  //
201  // Get information on the snapshot length.
202  status = nc_inq_dimid(ncid,"col",&col_id);
203  if (status != NC_NOERR) handle_error(status);
204  status = nc_inq_dimlen(ncid,col_id, &cols_t);
205  if (status != NC_NOERR) handle_error(status);
206  //
207  // Get number of nodal variables.
208  status=nc_inq_dimid(ncid,"num_nod_var",&num_nod_var_id);
209  if (status != NC_NOERR) handle_error(status);
210  status=nc_inq_dimlen(ncid,num_nod_var_id,&num_nod_var_t);
211  if (status != NC_NOERR) handle_error(status);
212  //
213  //
214  TEUCHOS_TEST_FOR_EXCEPTION(cols_t != cols0 || (int)num_nod_var_t != num_nod_var, std::runtime_error, "Data set in file "+temp_filename+" is of inconsistent size!");
215  total_rows += rows_t;
216  //
217  // If the scaling index vector is needed we can set the endpoint here.
218  //
219  if (createSSIdx) {
220  idx_pair.second = total_rows-1;
221  scaling_idx.push_back( idx_pair );
222  }
223  // Close the file.
224  status = nc_close(ncid);
225  if (status != NC_NOERR) handle_error(status);
226  }
227 
228  // Convert from size_t to int.
229  num_ss = total_rows;
230  num_vars = cols0;
231 
232  std::cout<<"Number of snapshots: "<< num_ss << std::endl;
233  std::cout<<"Length of snapshot : "<< num_vars << std::endl;
234  }
235  // Broadcast information about size of snapshot matrix.
236  comm.Broadcast( &num_ss, 1, 0 );
237  comm.Broadcast( &num_vars, 1, 0 );
238  //
239  // Sync all other processors on the scaling index vector if necessary
240  //
241  if (createSSIdx) {
242  for (i=0; i<(int)filenames.size(); i++) {
243  if ( comm.MyPID() != 0 )
244  scaling_idx.push_back( idx_pair );
245  comm.Broadcast( &scaling_idx[i].first, 1, 0 );
246  comm.Broadcast( &scaling_idx[i].second, 1, 0 );
247  }
248  // Set the scaling index vector
249  //params_->set("Snapshot Scaling Indices", scaling_idx);
250  }
251  //
252  // Create maps for new Epetra_MultiVector to hold the snapshots and
253  // temporary Epetra_Vector used by processor 0 to import the information.
254  //
255  Epetra_Map Map( num_vars, 0, comm );
257  Epetra_Vector *col_newMV = 0;
258  Epetra_Map *Proc0Map = 0;
259  int *index = 0;
260  float *temp_vec_f = 0;
261  double *temp_vec_d = 0;
262  //
263  if ( comm.MyPID() == 0 ) {
264  Proc0Map = new Epetra_Map( num_vars, num_vars, 0, comm );
265  temp_vec_f = new float [ num_vars ];
266  temp_vec_d = new double [ num_vars ];
267  index = new int[ num_vars ];
268  for ( i=0; i<num_vars; i++ ) { index[i] = i; }
269  } else {
270  Proc0Map = new Epetra_Map( num_vars, 0, 0, comm );
271  }
272  //
273  // Create an importer to get this information into the global Epetra_MultiVector
274  //
275  Epetra_Import importer( Map, *Proc0Map );
276  //
277  // Processor 0 reads each file and then creates a local Epetra_Vector, which will be
278  // imported into the i-th column of the Epetra_MultiVector.
279  //
280  // Read starting with row "start2[0]" for "count2[0]" rows, as the columns vary from
281  // "start2[1]" to "count2[1]", i.e. specifically for this case, read starting with row i
282  // for 1 row, as the columns vary from first column to the last column
283  //
284  start2[1]=0;
285  count2[0]=1;
286  count2[1]=num_vars;
287  col_ptr = 0;
288  //
289  for (i=0; i<(int)filenames.size(); i++) {
290 
291  if ( comm.MyPID() == 0 ) {
292  // Open the next snapshot file;
293  std::string temp_filename = in_path + filenames[i];
294  status = nc_open(temp_filename.c_str(),NC_NOWRITE,&ncid);
295  if (status != NC_NOERR) handle_error(status);
296  //
297  // Get information on the number of snapshots in the file.
298  status = nc_inq_dimid(ncid,"row",&row_id);
299  if (status != NC_NOERR) handle_error(status);
300  status = nc_inq_dimlen(ncid,row_id, &rows_t);
301 
302  if (status != NC_NOERR) handle_error(status);
303  // Get the pointer for the snapshot matrix
304  status = nc_inq_varid(ncid,"snapshot",&ss_id);
305  if (status != NC_NOERR) handle_error(status);
306  //
307  // Convert from size_t to int.
308  rows = rows_t;
309  }
310  comm.Broadcast( &rows, 1, 0 );
311 
312  for (j=0; j<rows; j++) {
313  //
314  // Get column of Epetra_MultiVector in terms of Epetra_Vector.
315  //
316  col_newMV = (*newMV)( col_ptr );
317  //
318  // Let Processor 0 fill in the Epetra_Vector.
319  //
320  if ( comm.MyPID() == 0 ) {
321  //
322  // Read in next snapshot, set pointer to next row containing snapshot in NetCDF file.
323  //
324  start2[0]=j;
325  status=nc_get_vara_float(ncid,ss_id,start2,count2,temp_vec_f);
326  for (k=0; k<num_vars; k++) {
327  temp_vec_d[k] = temp_vec_f[k];
328  }
329  }
330  //
331  // Create the Proc0Vector with values from temp_vec_d
332  //
333  Epetra_Vector Proc0Vector( View, *Proc0Map, temp_vec_d );
334  //
335  // Import the information.
336  //
337  col_newMV->Import(Proc0Vector, importer, Add);
338  //
339  // Increment the counter.
340  //
341  col_ptr++;
342  }
343  //
344  // Close this snapshot file.
345  if ( comm.MyPID() == 0 ) {
346  status = nc_close(ncid);
347  if (status != NC_NOERR) handle_error(status);
348  }
349  }
350  //
351  // Clean up
352  delete Proc0Map;
353  if ( index ) delete [] index;
354  if ( temp_vec_f ) delete [] temp_vec_f;
355  if ( temp_vec_d ) delete [] temp_vec_d;
356 
357  // Return.
358  return newMV;
359  }
360 
361  void NetCDFFileIOHandler::Write( const Teuchos::RCP<const Epetra_MultiVector>& MV, const std::string& filename )
362  {
363 #ifdef EPETRA_MPI
364  Epetra_MpiComm comm( MPI_COMM_WORLD );
365 #else
366  Epetra_SerialComm comm;
367 #endif
368  //
369  // Variables for NetCDF
370  //
371  int status;
372  int ncid, len_string_id, num_nodes_id, num_nod_var_id, row_id, col_id, ss_id, name_nod_var_id;
373  int i,j;
374  int ss_dimids[2];
375 
376  //size_t start[1],count[1];
377  size_t start2[2],count2[2];
378  //
379  // Variables for Epetra
380  //
381  int num_vecs = MV->NumVectors();
382  int dim = MV->GlobalLength();
383  Epetra_Map Map( dim, 0, comm );
384  Epetra_Map* Proc0Map;
385  const Epetra_Vector* col_newMV;
386  //
387  // Create map putting all elements of vector on Processor 0.
388  //
389  if ( comm.MyPID() == 0 ) {
390  Proc0Map = new Epetra_Map( dim, dim, 0, comm );
391  } else {
392  Proc0Map = new Epetra_Map( dim, 0, 0, comm );
393  }
394  Epetra_Vector Proc0Vector( *Proc0Map );
395  //
396  // Create an exporter to get the global Epetra_Vector to a local Epetra_Vector.
397  //
398  Epetra_Export exporter( MV->Map(), *Proc0Map );
399  //
400  if ( comm.MyPID() == 0 ) {
401  //
402  // Open basis output file and define output variables going into the file.
403  //
404  std::string temp_filename = out_path + filename;
405  status=nc_create(temp_filename.c_str(),NC_CLOBBER,&ncid);
406  if (status != NC_NOERR) handle_error(status);
407 
408  status=nc_def_dim(ncid,"len_string",(long)len_string,&len_string_id);
409  if (status != NC_NOERR) handle_error(status);
410 
411  status=nc_def_dim(ncid,"num_nodes",(long)num_nodes,&num_nodes_id);
412  if (status != NC_NOERR) handle_error(status);
413 
414  status=nc_def_dim(ncid,"num_nod_var",(long)num_nod_var,&num_nod_var_id);
415  if (status != NC_NOERR) handle_error(status);
416 
417  status=nc_def_dim(ncid,"row",NC_UNLIMITED,&row_id);
418  if (status != NC_NOERR) handle_error(status);
419 
420  status=nc_def_dim(ncid,"col",(long)dim,&col_id);
421  if (status != NC_NOERR) handle_error(status);
422 
423  ss_dimids[0]=row_id;
424  ss_dimids[1]=col_id;
425  status=nc_def_var(ncid,"snapshot",NC_FLOAT,2,ss_dimids,&ss_id);
426  if (status != NC_NOERR) handle_error(status);
427 
428  ss_dimids[0]=num_nod_var_id;
429  ss_dimids[1]=len_string_id;
430  status=nc_def_var(ncid,"name_nod_var",NC_CHAR,2,ss_dimids,&name_nod_var_id);
431  if (status != NC_NOERR) handle_error(status);
432 
433  status=nc_enddef(ncid);
434  if (status != NC_NOERR) handle_error(status);
435 
436  }
437 
438  // Initialize data pointers for writing out basis to file.
439  float* temp_vec = 0;
440  if ( comm.MyPID() == 0 )
441  temp_vec = new float[ dim ];
442 
443  for (i=0; i<num_vecs; ++i) {
444  //
445  // Get column of Epetra_MultiVector in terms of Epetra_Vector.
446  //
447  col_newMV = (*MV)( i );
448  //
449  Proc0Vector.Export(*col_newMV, exporter, Insert);
450  //
451  if ( comm.MyPID()==0 ) {
452  start2[0] = i;
453  start2[1] = 0;
454  count2[0] = 1;
455  count2[1] = dim;
456  //
457  // Copy double precision vector to single precision and write out.
458  //
459  for (j=0; j<dim; ++j)
460  temp_vec[j] = Proc0Vector[j];
461 
462  status=nc_put_vara_float(ncid,ss_id,start2,count2,temp_vec);
463  if (status != NC_NOERR) handle_error(status);
464  }
465  }
466 
467  // Write the list of names of the nodal variables to the Netcdf file */
468  if ( comm.MyPID() == 0 ) {
469  for(i=0; i<num_nod_var; ++i) {
470  start2[0] = i;
471  start2[1] = 0;
472  count2[0] = 1;
473  count2[1] = strlen(var_name[i]);
474  /* printf("start2=%d %d\n",start2[0],start2[1]);
475  printf("count2=%d %d\n",count2[0],count2[1]); */
476 
477  status=nc_put_vara_text(ncid,name_nod_var_id,start2,count2,var_name[i]);
478  if (status != NC_NOERR) handle_error(status);
479  }
480 
481  status=nc_close(ncid);
482  if (status != NC_NOERR) handle_error(status);
483  }
484 
485  // Clean up.
486  delete Proc0Map;
487  if (temp_vec) delete [] temp_vec;
488  }
489 
490 } // namespace RBGen
491 
492 
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
int MyPID() const
bool isParameter(const std::string &name) const
Teuchos::RCP< Epetra_MultiVector > Read(const std::vector< std::string > &filenames)
Method for reading multiple files and putting them into an Epetra_MultiVector.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
NetCDFFileIOHandler()
Default constructor.
void Write(const Teuchos::RCP< const Epetra_MultiVector > &MV, const std::string &filename)
Method for writing one Epetra_MultiVector into a file.
virtual ~NetCDFFileIOHandler()
Destructor.
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
int Broadcast(double *MyVals, int Count, int Root) const
void Initialize(const Teuchos::RCP< Teuchos::ParameterList > &params)
Initialize file reader using.