MFEM  v4.4.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
get-values.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 //
12 // --------------------------------------------------------------------
13 // Get Values Miniapp: Extract field values via DataCollection classes
14 // --------------------------------------------------------------------
15 //
16 // This miniapp loads previously saved data using DataCollection sub-classes,
17 // see e.g. load-dc miniapp and Example 5/5p, and output field values at a
18 // set of points. Currently, only the VisItDataCollection class is supported.
19 //
20 // Compile with: make get-values
21 //
22 // Serial sample runs:
23 // > get-values -r ../../examples/Example5 -p "0 0 0.1 0" -fn pressure
24 //
25 // Parallel sample runs:
26 // > mpirun -np 4 get-values -r ../electromagnetics/Volta-AMR-Parallel
27 // -c 1 -p "0 0 0 0.1 0.1 0.1" -fn ALL
28 //
29 // Point locations can be specified on the command line using -p or within a
30 // data file whose name can be given with option -pf. The data file format is:
31 //
32 // number_of_points space_dimension
33 // x_0 y_0 ...
34 // x_1 y_1 ...
35 // etc.
36 //
37 // By default all available fields are evaluated. The list of fields can be
38 // reduced by specifying the desired field names with -fn. The -fn option
39 // takes a space separated list of field names surrounded by qoutes. Field
40 // names containing spaces, such as "Field 1" and "Field 2", can be entered as:
41 // get-values -fn "Field\ 1 Field\ 2"
42 //
43 // By default the data is written to standard out. This can be overwritten
44 // with the -o [filename] option.
45 //
46 // The output format contains comments as well as sizing information to aid in
47 // subsequent processing. The bulk of the data consists of one line per point
48 // with a 0-based integer index followed by the point coordinates and then the
49 // field data. A legend, appearing before the bulk data, shows the order of
50 // the fields along with the number of values per field (for vector data).
51 //
52 #include "mfem.hpp"
53 
54 #include <fstream>
55 #include <set>
56 #include <string>
57 
58 using namespace std;
59 using namespace mfem;
60 
61 void parseFieldNames(const char * field_name_c_str, set<string> &field_names);
62 void parsePoints(int spaceDim, const char *pts_file_c_str, Vector &pts);
63 void writeLegend(const DataCollection::FieldMapType &fields,
64  const set<string> & field_names, int spaceDim);
65 
66 int main(int argc, char *argv[])
67 {
68 #ifdef MFEM_USE_MPI
69  Mpi::Init();
70  if (!Mpi::Root()) { mfem::out.Disable(); mfem::err.Disable(); }
71  Hypre::Init();
72 #endif
73 
74  // Parse command-line options.
75  const char *coll_name = NULL;
76  int cycle = 0;
77 
78  const char *field_name_c_str = "ALL";
79  const char *pts_file_c_str = "";
80  Vector pts;
81 
82  const char *out_file_c_str = "";
83 
84  OptionsParser args(argc, argv);
85  args.AddOption(&coll_name, "-r", "--root-file",
86  "Set the VisIt data collection root file prefix.", true);
87  args.AddOption(&cycle, "-c", "--cycle", "Set the cycle index to read.");
88  args.AddOption(&pts, "-p", "--points", "List of points.");
89  args.AddOption(&field_name_c_str, "-fn", "--field-names",
90  "List of field names to get values from.");
91  args.AddOption(&pts_file_c_str, "-pf", "--point-file",
92  "Filename containing a list of points.");
93  args.AddOption(&out_file_c_str, "-o", "--output-file",
94  "Output filename.");
95  args.Parse();
96  if (!args.Good())
97  {
98  args.PrintUsage(mfem::out);
99  return 1;
100  }
101  args.PrintOptions(mfem::out);
102 
103 #ifdef MFEM_USE_MPI
104  VisItDataCollection dc(MPI_COMM_WORLD, coll_name);
105 #else
106  VisItDataCollection dc(coll_name);
107 #endif
108  dc.Load(cycle);
109 
110  if (dc.Error() != DataCollection::NO_ERROR)
111  {
112  mfem::out << "Error loading VisIt data collection: " << coll_name << endl;
113  return 1;
114  }
115 
116  int spaceDim = dc.GetMesh()->SpaceDimension();
117 
118  mfem::out << endl;
119  mfem::out << "Collection Name: " << dc.GetCollectionName() << endl;
120  mfem::out << "Space Dimension: " << spaceDim << endl;
121  mfem::out << "Cycle: " << dc.GetCycle() << endl;
122  mfem::out << "Time: " << dc.GetTime() << endl;
123  mfem::out << "Time Step: " << dc.GetTimeStep() << endl;
124  mfem::out << endl;
125 
126  typedef DataCollection::FieldMapType fields_t;
127  const fields_t &fields = dc.GetFieldMap();
128  // Print the names of all fields.
129  mfem::out << "fields: [ ";
130  for (fields_t::const_iterator it = fields.begin(); it != fields.end(); ++it)
131  {
132  if (it != fields.begin()) { mfem::out << ", "; }
133  mfem::out << it->first;
134  }
135  mfem::out << " ]" << endl;
136 
137  // Parsing desired field names
138  set<string> field_names;
139  parseFieldNames(field_name_c_str, field_names);
140 
141  // Print field names to be extracted
142  mfem::out << "Extracting fields: ";
143  for (set<string>::iterator it=field_names.begin();
144  it!=field_names.end(); it++)
145  {
146  mfem::out << " \"" << *it << "\"";
147  }
148  mfem::out << endl;
149 
150  parsePoints(spaceDim, pts_file_c_str, pts);
151  int npts = pts.Size() / spaceDim;
152 
153  DenseMatrix pt_mat(pts.GetData(), spaceDim, npts);
154 
155  Array<int> elem_ids;
157  int nfound = dc.GetMesh()->FindPoints(pt_mat, elem_ids, ip);
158  mfem::out << "Found " << nfound << " points." << endl;
159 
160  ofstream ofs;
161  if (strcmp(out_file_c_str,"") != 0
162 #ifdef MFEM_USE_MPI
163  && Mpi::Root()
164 #endif
165  )
166  {
167  ofs.open(out_file_c_str);
168  if (!ofs)
169  {
170  MFEM_ABORT("Failed to open output file: " << out_file_c_str << '\n');
171  }
172 
173  mfem::out.SetStream(ofs);
174  }
175 
176  // Write legend showing the order of the fields and their sizes
177  writeLegend(fields, field_names, spaceDim);
178 
179  mfem::out << "# Number of points\n" << nfound << endl;
180 
181  for (int e=0; e<elem_ids.Size(); e++)
182  {
183  if (elem_ids[e] >= 0)
184  {
185  mfem::out << e;
186  for (int d=0; d<spaceDim; d++)
187  {
188  mfem::out << ' ' << pt_mat(d, e);
189  }
190 
191  // Loop over all fields.
192  for (fields_t::const_iterator it = fields.begin();
193  it != fields.end(); ++it)
194  {
195  if (field_names.find("ALL") != field_names.end() ||
196  field_names.find(it->first) != field_names.end())
197  {
198  if (it->second->VectorDim() == 1)
199  {
200  mfem::out << ' ' << it->second->GetValue(elem_ids[e], ip[e]);
201  }
202  else
203  {
204  Vector val;
205  it->second->GetVectorValue(elem_ids[e], ip[e], val);
206  for (int d=0; d<it->second->VectorDim(); d++)
207  {
208  mfem::out << ' ' << val[d];
209  }
210  }
211  }
212  }
213  mfem::out << endl;
214  }
215  }
216  if (ofs) { ofs.close(); }
217 
218  return 0;
219 }
220 
221 void parseFieldNames(const char * field_name_c_str, set<string> &field_names)
222 {
223  string field_name_str(field_name_c_str);
224  string field_name;
225 
226  for (string::iterator it=field_name_str.begin();
227  it!=field_name_str.end(); it++)
228  {
229  if (*it == '\\')
230  {
231  it++;
232  field_name.push_back(*it);
233  }
234  else if (*it == ' ')
235  {
236  if (!field_name.empty())
237  {
238  field_names.insert(field_name);
239  }
240  field_name.clear();
241  }
242  else if (it == field_name_str.end() - 1)
243  {
244  field_name.push_back(*it);
245  field_names.insert(field_name);
246  }
247  else
248  {
249  field_name.push_back(*it);
250  }
251  }
252  if (field_names.size() == 0)
253  {
254  field_names.insert("ALL");
255  }
256 }
257 
258 void parsePoints(int spaceDim, const char *pts_file_c_str, Vector &pts)
259 {
260  if (strcmp(pts_file_c_str,"") == 0) { return; }
261 
262  ifstream ifs(pts_file_c_str);
263 
264  if (!ifs)
265  {
266  MFEM_ABORT("Failed to open point file: " << pts_file_c_str << '\n');
267  }
268 
269  int o, n, dim;
270  ifs >> n >> dim;
271 
272  MFEM_VERIFY(dim == spaceDim, "Mismatch in mesh's space dimension "
273  "and point dimension.");
274 
275  if (pts.Size() > 0 && pts.Size() % spaceDim == 0)
276  {
277  int size = pts.Size() + n * dim;
278  Vector tmp(size);
279  for (int i=0; i<pts.Size(); i++)
280  {
281  tmp[i] = pts[i];
282  }
283  o = pts.Size();
284  pts.Swap(tmp);
285  }
286  else
287  {
288  pts.SetSize(n * dim);
289  o = 0;
290  }
291 
292  for (int i=0; i<n; i++)
293  {
294  for (int d=0; d<dim; d++)
295  {
296  ifs >> pts[o + i * dim + d];
297  }
298  }
299 
300  ifs.close();
301 }
302 
304  const set<string> & field_names, int spaceDim)
305 {
306  typedef DataCollection::FieldMapType fields_t;
307 
308  // Count the number of fields to be output
309  int nfields = 1;
310  for (fields_t::const_iterator it = fields.begin();
311  it != fields.end(); ++it)
312  {
313  if (field_names.find("ALL") != field_names.end() ||
314  field_names.find(it->first) != field_names.end())
315  {
316  nfields++;
317  }
318  }
319 
320  // Write the legend showing each field name and its number of entries
321  mfem::out << "# Number of fields" << endl << nfields << endl;
322  mfem::out << "# Legend" << endl;
323  mfem::out << "# \"Index\" \"Location\":" << spaceDim;
324  for (fields_t::const_iterator it = fields.begin();
325  it != fields.end(); ++it)
326  {
327  if (field_names.find("ALL") != field_names.end() ||
328  field_names.find(it->first) != field_names.end())
329  {
330  mfem::out << " \"" << it->first << "\":" << it->second->VectorDim();
331  }
332  }
333  mfem::out << endl;
334 
335  // Write the number of entries for each field without the names
336  // which should be more convenient for parsing the output file.
337  mfem::out << spaceDim;
338  for (fields_t::const_iterator it = fields.begin();
339  it != fields.end(); ++it)
340  {
341  if (field_names.find("ALL") != field_names.end() ||
342  field_names.find(it->first) != field_names.end())
343  {
344  mfem::out << " " << it->second->VectorDim();
345  }
346  }
347  mfem::out << endl;
348 }
void writeLegend(const DataCollection::FieldMapType &fields, const set< string > &field_names, int spaceDim)
Definition: get-values.cpp:303
double GetTime() const
Get physical time (for time-dependent simulations)
void SetSize(int s)
Resize the vector to size s.
Definition: vector.hpp:521
const std::string & GetCollectionName() const
Get the name of the collection.
void parsePoints(int spaceDim, const char *pts_file_c_str, Vector &pts)
Definition: get-values.cpp:258
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
int Size() const
Returns the size of the vector.
Definition: vector.hpp:199
int Error() const
Get the current error state.
void SetStream(std::ostream &os)
Replace the rdbuf() and tie() of the OutStream with that of os, enabling output.
Definition: globals.hpp:46
double * GetData() const
Return a pointer to the beginning of the Vector data.
Definition: vector.hpp:208
double GetTimeStep() const
Get the simulation time step (for time-dependent simulations)
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
Definition: optparser.cpp:151
void Swap(Vector &other)
Swap the contents of two Vectors.
Definition: vector.hpp:623
const FieldMapType & GetFieldMap() const
Get a const reference to the internal field map.
int GetCycle() const
Get time cycle (for time-dependent simulations)
Data collection with VisIt I/O routines.
void parseFieldNames(const char *field_name_c_str, set< string > &field_names)
Definition: get-values.cpp:221
void PrintUsage(std::ostream &out) const
Print the usage message.
Definition: optparser.cpp:454
virtual void Load(int cycle_=0)
Load the collection based on its VisIt data (described in its root file)
int SpaceDimension() const
Definition: mesh.hpp:1000
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
Definition: globals.hpp:71
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set &#39;var&#39; to receive the value. Enable/disable tags are used to set the bool...
Definition: optparser.hpp:82
void Disable()
Disable output.
Definition: globals.hpp:54
GFieldMap::MapType FieldMapType
int dim
Definition: ex24.cpp:53
void PrintOptions(std::ostream &out) const
Print the options.
Definition: optparser.cpp:324
Mesh * GetMesh()
Get a pointer to the mesh in the collection.
virtual int FindPoints(DenseMatrix &point_mat, Array< int > &elem_ids, Array< IntegrationPoint > &ips, bool warn=true, InverseElementTransformation *inv_trans=NULL)
Find the ids of the elements that contain the given points, and their corresponding reference coordin...
Definition: mesh.cpp:11820
Vector data type.
Definition: vector.hpp:60
void pts(int iphi, int t, double x[])
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:66
int main()
bool Good() const
Return true if the command line options were parsed successfully.
Definition: optparser.hpp:150