OGS
TecPlotTools.cpp File Reference

Detailed Description

Definition in file TecPlotTools.cpp.

#include <tclap/CmdLine.h>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include "BaseLib/StringTools.h"
#include "GeoLib/Point.h"
#include "InfoLib/GitInfo.h"
#include "MeshLib/IO/VtkIO/VtuInterface.h"
#include "MeshLib/Mesh.h"
#include "MeshLib/MeshGenerators/RasterToMesh.h"
Include dependency graph for TecPlotTools.cpp:

Go to the source code of this file.

Functions

std::string getValue (std::string const &line, std::string const &val_name, bool is_string)
 
std::string getName (std::string const &line)
 Returns the name/title from the "Zone"-description. More...
 
std::string_view getZonetype (std::string const &line)
 
std::pair< std::size_t, std::size_t > getDimensions (std::string const &line)
 Returns raster dimensions from the "Zone"-description. More...
 
std::string trimVariable (std::string &var)
 Trims a substring containing a variable-name. More...
 
std::vector< std::string > getVariables (std::string const &line)
 Returns an vector of variable names from the "Variables"-description. More...
 
bool dataCountError (std::string const &name, std::size_t const &current, std::size_t const &total)
 Tests if the number of read values equals the number of expected values. More...
 
bool dataCountError (std::ofstream &out, std::string const &name, std::size_t const &current, std::size_t const &total)
 
void resetDataStructures (std::size_t const &n_scalars, std::vector< std::vector< double >> &scalars, std::size_t &val_count)
 Resets all data structures after a new "Variables"-description is found. More...
 
void writeTecPlotSection (std::ofstream &out, std::string const &file_name, std::size_t &write_count, std::size_t &val_count, std::size_t &val_total)
 Writes one section/zone into a separate TecPlot file. More...
 
int writeDataToMesh (std::string const &file_name, std::size_t &write_count, std::vector< std::string > const &vec_names, std::vector< std::vector< double >> const &scalars, std::pair< std::size_t, std::size_t > const &dims)
 Writes one section/zone into a separate OGS-mesh. More...
 
void skipGeometrySection (std::ifstream &in, std::string &line)
 If a geometry-section is encountered, it is currently ignored. More...
 
int splitFile (std::ifstream &in, std::string const &file_name)
 Splits a TecPlot file containing multiple sections/zones into separate files. More...
 
int convertFile (std::ifstream &in, std::string const &file_name)
 
int main (int argc, char *argv[])
 

Function Documentation

◆ convertFile()

int convertFile ( std::ifstream &  in,
std::string const &  file_name 
)

Converts a TecPlot file into one or more OGS-meshes (one mesh per section/zone)

Definition at line 338 of file TecPlotTools.cpp.

339 {
340  std::string line;
341  std::string name;
342  std::pair<std::size_t, std::size_t> dims(0, 0);
343  std::vector<std::string> var_names;
344  std::vector<std::vector<double>> scalars;
345  std::size_t val_count(0);
346  std::size_t val_total(0);
347  std::size_t write_count(0);
348  while (std::getline(in, line))
349  {
350  if (line.find("GEOMETRY") != std::string::npos)
351  {
352  skipGeometrySection(in, line);
353  }
354 
355  if (line.empty())
356  {
357  continue;
358  }
359  if (line.find("TITLE") != std::string::npos)
360  {
361  if (dataCountError(name, val_count, val_total))
362  {
363  return -3;
364  }
365  if (val_count != 0)
366  {
367  writeDataToMesh(file_name, write_count, var_names, scalars,
368  dims);
369  resetDataStructures(var_names.size(), scalars, val_count);
370  }
371  continue;
372  }
373  if (line.find("VARIABLES") != std::string::npos)
374  {
375  if (val_count != 0)
376  {
377  if (dataCountError(name, val_count, val_total))
378  {
379  return -3;
380  }
381  writeDataToMesh(file_name, write_count, var_names, scalars,
382  dims);
383  }
384  var_names.clear();
385  var_names = getVariables(line);
386  resetDataStructures(var_names.size(), scalars, val_count);
387  continue;
388  }
389  if (line.find("ZONE") != std::string::npos)
390  {
391  if (val_count != 0)
392  {
393  if (dataCountError(name, val_count, val_total))
394  {
395  return -3;
396  }
397  writeDataToMesh(file_name, write_count, var_names, scalars,
398  dims);
399  resetDataStructures(var_names.size(), scalars, val_count);
400  }
401  name = getName(line);
402  if (auto const zonetype = getZonetype(line); zonetype != "ORDERED")
403  {
404  ERR("Given zonetype '{:s}' is not supported. Only 'ORDERED' "
405  "zonetype data can be converted.",
406  zonetype);
407  return -4;
408  }
409  dims = getDimensions(line);
410  val_total = dims.first * dims.second;
411  val_count = 0;
412  continue;
413  }
414 
415  double x;
416  std::stringstream iss(line);
417  std::size_t i(0);
418  std::size_t const n_scalars(scalars.size());
419  while (iss >> x)
420  {
421  if (i > n_scalars - 1)
422  {
423  ERR("Too much data for existing scalar arrays");
424  return -3;
425  }
426  scalars[i++].push_back(x);
427  }
428  if (i < n_scalars)
429  {
430  ERR("Not enough data for existing scalar arrays");
431  return -3;
432  }
433  val_count++;
434  }
435  if (dataCountError(name, val_count, val_total))
436  {
437  return -3;
438  }
439  writeDataToMesh(file_name, write_count, var_names, scalars, dims);
440  INFO("Finished conversion.");
441  return 0;
442 }
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
std::string getName(std::string const &line)
Returns the name/title from the "Zone"-description.
std::string_view getZonetype(std::string const &line)
bool dataCountError(std::string const &name, std::size_t const &current, std::size_t const &total)
Tests if the number of read values equals the number of expected values.
std::vector< std::string > getVariables(std::string const &line)
Returns an vector of variable names from the "Variables"-description.
void skipGeometrySection(std::ifstream &in, std::string &line)
If a geometry-section is encountered, it is currently ignored.
int writeDataToMesh(std::string const &file_name, std::size_t &write_count, std::vector< std::string > const &vec_names, std::vector< std::vector< double >> const &scalars, std::pair< std::size_t, std::size_t > const &dims)
Writes one section/zone into a separate OGS-mesh.
void resetDataStructures(std::size_t const &n_scalars, std::vector< std::vector< double >> &scalars, std::size_t &val_count)
Resets all data structures after a new "Variables"-description is found.
std::pair< std::size_t, std::size_t > getDimensions(std::string const &line)
Returns raster dimensions from the "Zone"-description.

References dataCountError(), ERR(), getDimensions(), getName(), getVariables(), getZonetype(), INFO(), MaterialPropertyLib::name, resetDataStructures(), skipGeometrySection(), and writeDataToMesh().

Referenced by main().

◆ dataCountError() [1/2]

bool dataCountError ( std::ofstream &  out,
std::string const &  name,
std::size_t const &  current,
std::size_t const &  total 
)

Tests if the number of read values equals the number of expected values and closes the stream

Definition at line 153 of file TecPlotTools.cpp.

157 {
158  if (dataCountError(name, current, total))
159  {
160  out.close();
161  return true;
162  }
163  return false;
164 }

References dataCountError(), and MaterialPropertyLib::name.

◆ dataCountError() [2/2]

bool dataCountError ( std::string const &  name,
std::size_t const &  current,
std::size_t const &  total 
)

Tests if the number of read values equals the number of expected values.

Definition at line 137 of file TecPlotTools.cpp.

140 {
141  if (current != total)
142  {
143  ERR("Data rows found do not fit specified dimensions for section "
144  "'{:s}'.",
145  name);
146  return true;
147  }
148  return false;
149 }

References ERR(), and MaterialPropertyLib::name.

Referenced by convertFile(), dataCountError(), and splitFile().

◆ getDimensions()

std::pair<std::size_t, std::size_t> getDimensions ( std::string const &  line)

Returns raster dimensions from the "Zone"-description.

Definition at line 92 of file TecPlotTools.cpp.

93 {
94  std::pair<std::size_t, std::size_t> dims;
95  std::stringstream start(getValue(line, "I=", false));
96  start >> dims.first;
97  std::stringstream end(getValue(line, "J=", false));
98  end >> dims.second;
99  return dims;
100 }
std::string getValue(std::string const &line, std::string const &val_name, bool is_string)

References getValue().

Referenced by convertFile(), and splitFile().

◆ getName()

◆ getValue()

std::string getValue ( std::string const &  line,
std::string const &  val_name,
bool  is_string 
)

Returns the value for the given parameter name (i.e. for "x = 3" it returns "3")

Definition at line 27 of file TecPlotTools.cpp.

30 {
31  std::string value;
32  std::size_t start(line.find(val_name));
33  std::size_t end(std::string::npos);
34  if (start == end)
35  {
36  ERR("Value not found.");
37  return "";
38  }
39  value = line.substr(start + 1, std::string::npos);
40  if (is_string)
41  {
42  start = value.find("\"");
43  value = value.substr(start + 1, std::string::npos);
44  end = value.find("\"");
45  }
46  else
47  {
48  start = value.find_first_not_of(" ");
49  value = value.substr(start + 1, std::string::npos);
50  BaseLib::trim(value);
51  end = value.find_first_of(" ");
52  }
53  value = value.substr(0, end);
54  BaseLib::trim(value);
55  return value;
56 }
void trim(std::string &str, char ch)
Definition: StringTools.cpp:58

References ERR(), and BaseLib::trim().

Referenced by getDimensions(), getName(), MaterialLib::Fluid::FluidPropertiesWithDensityDependentModels::getValue(), and main().

◆ getVariables()

std::vector<std::string> getVariables ( std::string const &  line)

Returns an vector of variable names from the "Variables"-description.

Definition at line 112 of file TecPlotTools.cpp.

113 {
114  std::string const var_str("VARIABLES");
115  std::size_t start(line.find(var_str));
116  std::string all_vars =
117  line.substr(start + var_str.length(), std::string::npos);
118  start = all_vars.find("=");
119  all_vars = all_vars.substr(start + 1, std::string::npos);
120  BaseLib::trim(all_vars);
121 
122  std::vector<std::string> variables;
123  std::size_t end = 0;
124  while (end != std::string::npos)
125  {
126  end = all_vars.find_first_of(" ");
127  std::string var = all_vars.substr(0, end);
128  variables.push_back(trimVariable(var));
129  all_vars = all_vars.substr(end + 1, std::string::npos);
130  BaseLib::trim(all_vars);
131  }
132 
133  return variables;
134 }
std::string trimVariable(std::string &var)
Trims a substring containing a variable-name.

References BaseLib::trim(), and trimVariable().

Referenced by convertFile().

◆ getZonetype()

std::string_view getZonetype ( std::string const &  line)

Definition at line 64 of file TecPlotTools.cpp.

65 {
66  auto start = line.find("ZONETYPE=");
67  if (start == std::string::npos)
68  {
69  OGS_FATAL(
70  "A required 'ZONETYPE=' substring is not available in the ZONE "
71  "description: '{:s}'.",
72  line);
73  }
74  start += std::size("ZONETYPE=") - 1;
75 
76  auto end = line.find(',', start);
77  if (end == std::string::npos)
78  {
79  OGS_FATAL(
80  "Expected the 'ZONETYPE=type' to be followed by a comma in the "
81  "ZONE description '{:s}'. The zone type starts at position {:d}.",
82  line, start);
83  }
84  if (start == end)
85  {
86  ERR("ZONETYPE string is empty in ZONE description '{:s}'.", line);
87  }
88  return std::string_view(&line[start], end - start);
89 }
#define OGS_FATAL(...)
Definition: Error.h:26

References ERR(), and OGS_FATAL.

Referenced by convertFile().

◆ main()

int main ( int  argc,
char *  argv[] 
)

Small collection of scripts to handle TecPlot files.

Return codes: 0 : no errors -1 : missing arguments -2 : file I/O error -3 : index error -4 : error interpreting data -5 : error creating data structures

Definition at line 455 of file TecPlotTools.cpp.

456 {
457  TCLAP::CmdLine cmd(
458  "TecPlot Parser\n\n"
459  "OpenGeoSys-6 software, version " +
461  ".\n"
462  "Copyright (c) 2012-2022, OpenGeoSys Community "
463  "(http://www.opengeosys.org)",
465  TCLAP::SwitchArg split_arg("s", "split",
466  "split time steps into separate files");
467  cmd.add(split_arg);
468  TCLAP::SwitchArg convert_arg("c", "convert",
469  "convert TecPlot data into OGS meshes");
470  cmd.add(convert_arg);
471  TCLAP::ValueArg<std::string> output_arg(
472  "o", "output-file", "output mesh file", false, "", "string");
473  cmd.add(output_arg);
474  TCLAP::ValueArg<std::string> input_arg(
475  "i", "input-file", "TecPlot input file", true, "", "string");
476  cmd.add(input_arg);
477  cmd.parse(argc, argv);
478 
479  if (!input_arg.isSet())
480  {
481  ERR("No input file given. Please specify TecPlot (*.plt) file");
482  return -1;
483  }
484 
485  if (convert_arg.getValue() && !output_arg.isSet())
486  {
487  ERR("No output file given. Please specify OGS mesh (*.vtu) file");
488  return -1;
489  }
490 
491  std::ifstream in(input_arg.getValue().c_str());
492  if (!in.is_open())
493  {
494  ERR("Could not open file {:s}.", input_arg.getValue());
495  return -2;
496  }
497 
498  if (!convert_arg.isSet() && !split_arg.isSet())
499  {
500  INFO("Nothing to do. Use -s to split or -c to convert.");
501  return 0;
502  }
503 
504  std::string const filename =
505  (output_arg.isSet()) ? output_arg.getValue() : input_arg.getValue();
506  int return_val(0);
507  if (split_arg.getValue())
508  {
509  return_val = splitFile(in, filename);
510  }
511  else if (convert_arg.getValue())
512  {
513  return_val = convertFile(in, filename);
514  }
515 
516  in.close();
517  return return_val;
518 }
int convertFile(std::ifstream &in, std::string const &file_name)
int splitFile(std::ifstream &in, std::string const &file_name)
Splits a TecPlot file containing multiple sections/zones into separate files.
GITINFOLIB_EXPORT const std::string ogs_version

References convertFile(), ERR(), INFO(), GitInfoLib::GitInfo::ogs_version, and splitFile().

◆ resetDataStructures()

void resetDataStructures ( std::size_t const &  n_scalars,
std::vector< std::vector< double >> &  scalars,
std::size_t &  val_count 
)

Resets all data structures after a new "Variables"-description is found.

Definition at line 167 of file TecPlotTools.cpp.

170 {
171  scalars.clear();
172  scalars.reserve(n_scalars);
173  for (std::size_t i = 0; i < n_scalars; ++i)
174  {
175  scalars.emplace_back(0);
176  }
177  val_count = 0;
178 }

Referenced by convertFile().

◆ skipGeometrySection()

void skipGeometrySection ( std::ifstream &  in,
std::string &  line 
)

If a geometry-section is encountered, it is currently ignored.

Definition at line 261 of file TecPlotTools.cpp.

262 {
263  while (std::getline(in, line))
264  {
265  if ((line.find("TITLE") != std::string::npos) ||
266  (line.find("VARIABLES") != std::string::npos) ||
267  (line.find("ZONE") != std::string::npos))
268  {
269  return;
270  }
271  }
272 }

Referenced by convertFile().

◆ splitFile()

int splitFile ( std::ifstream &  in,
std::string const &  file_name 
)

Splits a TecPlot file containing multiple sections/zones into separate files.

Definition at line 275 of file TecPlotTools.cpp.

276 {
277  std::ofstream out;
278  std::string line;
279  std::string name;
280  std::size_t val_count(0);
281  std::size_t val_total(0);
282  std::size_t write_count(0);
283  while (std::getline(in, line))
284  {
285  if (line.find("TITLE") != std::string::npos)
286  {
287  if (dataCountError(out, name, val_count, val_total))
288  {
289  return -3;
290  }
291  writeTecPlotSection(out, file_name, write_count, val_count,
292  val_total);
293  out << line << "\n";
294  continue;
295  }
296  if (line.find("VARIABLES") != std::string::npos)
297  {
298  if (dataCountError(out, name, val_count, val_total))
299  {
300  return -3;
301  }
302  writeTecPlotSection(out, file_name, write_count, val_count,
303  val_total);
304  out << line << "\n";
305  continue;
306  }
307  if (line.find("ZONE") != std::string::npos)
308  {
309  if (dataCountError(out, name, val_count, val_total))
310  {
311  return -3;
312  }
313  writeTecPlotSection(out, file_name, write_count, val_count,
314  val_total);
315  out << line << "\n";
316  name = getName(line);
317  std::pair<std::size_t, std::size_t> dims = getDimensions(line);
318  val_total = dims.first * dims.second;
319  val_count = 0;
320  continue;
321  }
322 
323  out << line << "\n";
324  val_count++;
325  }
326  if (dataCountError(out, name, val_count, val_total))
327  {
328  return -3;
329  }
330  INFO("Writing time step #{:i}", write_count);
331  out.close();
332  INFO("Finished split.");
333  return 0;
334 }
void writeTecPlotSection(std::ofstream &out, std::string const &file_name, std::size_t &write_count, std::size_t &val_count, std::size_t &val_total)
Writes one section/zone into a separate TecPlot file.

References dataCountError(), getDimensions(), getName(), INFO(), MaterialPropertyLib::name, and writeTecPlotSection().

Referenced by main().

◆ trimVariable()

std::string trimVariable ( std::string &  var)

Trims a substring containing a variable-name.

Definition at line 103 of file TecPlotTools.cpp.

104 {
105  std::size_t const start = var.find_first_not_of("\"");
106  var = var.substr(start, std::string::npos);
107  std::size_t const end = var.find_first_of("\"");
108  return var.substr(0, end);
109 }

Referenced by getVariables().

◆ writeDataToMesh()

int writeDataToMesh ( std::string const &  file_name,
std::size_t &  write_count,
std::vector< std::string > const &  vec_names,
std::vector< std::vector< double >> const &  scalars,
std::pair< std::size_t, std::size_t > const &  dims 
)

Writes one section/zone into a separate OGS-mesh.

Definition at line 203 of file TecPlotTools.cpp.

208 {
209  double cellsize = 0;
210  for (std::size_t i = 0; i < vec_names.size(); ++i)
211  {
212  if (vec_names[i] == "x" || vec_names[i] == "X")
213  {
214  cellsize = scalars[i][1] - scalars[i][0];
215  break;
216  }
217  }
218 
219  if (cellsize == 0)
220  {
221  ERR("Cell size not found. Aborting...");
222  return -4;
223  }
224 
225  GeoLib::Point origin(0, 0, 0);
226  GeoLib::RasterHeader header{dims.first, dims.second, 1,
227  origin, cellsize, -9999};
228 
229  std::unique_ptr<MeshLib::Mesh> mesh(
230  MeshLib::RasterToMesh::convert(scalars[0].data(),
231  header,
234  vec_names[0]));
235  MeshLib::Properties& properties = mesh->getProperties();
236  for (std::size_t i = 1; i < vec_names.size(); ++i)
237  {
238  auto* const prop = properties.createNewPropertyVector<double>(
239  vec_names[i], MeshLib::MeshItemType::Cell, 1);
240  if (!prop)
241  {
242  ERR("Error creating array '{:s}'.", vec_names[i]);
243  return -5;
244  }
245  prop->reserve(scalars[i].size());
246  std::copy(scalars[i].cbegin(), scalars[i].cend(),
247  std::back_inserter(*prop));
248  }
249 
250  std::size_t const delim_pos(file_name.find_last_of("."));
251  std::string const base_name(file_name.substr(0, delim_pos + 1));
252  std::string const extension(file_name.substr(delim_pos, std::string::npos));
253 
254  INFO("Writing section #{:i}", write_count);
255  MeshLib::IO::VtuInterface vtu(mesh.get());
256  vtu.writeToFile(base_name + std::to_string(write_count++) + extension);
257  return 0;
258 }
Reads and writes VtkXMLUnstructuredGrid-files (vtu) to and from OGS data structures....
Definition: VtuInterface.h:38
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
Definition: Properties.h:36
PropertyVector< T > * createNewPropertyVector(std::string const &name, MeshItemType mesh_item_type, std::size_t n_components=1)
static std::unique_ptr< MeshLib::Mesh > convert(GeoLib::Raster const &raster, MeshElemType elem_type, UseIntensityAs intensity_type, std::string const &array_name="Colour")
void copy(PETScVector const &x, PETScVector &y)
Definition: LinAlg.cpp:37
Contains the relevant information when storing a geoscientific raster data.
Definition: Raster.h:27

References MeshLib::Cell, MeshLib::RasterToMesh::convert(), MathLib::LinAlg::copy(), MeshLib::Properties::createNewPropertyVector(), MeshLib::DATAVECTOR, ERR(), INFO(), MeshLib::QUAD, and MeshLib::IO::VtuInterface::writeToFile().

Referenced by convertFile().

◆ writeTecPlotSection()

void writeTecPlotSection ( std::ofstream &  out,
std::string const &  file_name,
std::size_t &  write_count,
std::size_t &  val_count,
std::size_t &  val_total 
)

Writes one section/zone into a separate TecPlot file.

Definition at line 181 of file TecPlotTools.cpp.

186 {
187  if (write_count == 0 || val_total != 0)
188  {
189  std::size_t const delim_pos(file_name.find_last_of("."));
190  std::string const base_name(file_name.substr(0, delim_pos + 1));
191  std::string const extension(
192  file_name.substr(delim_pos, std::string::npos));
193 
194  val_count = 0;
195  val_total = 0;
196  INFO("Writing section #{:i}", write_count);
197  out.close();
198  out.open(base_name + std::to_string(write_count++) + extension);
199  }
200 }

References INFO().

Referenced by splitFile().