Nektar++
CsvIO.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: CsvIO.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2017 Kilian Lackhove
10 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
11 // Department of Aeronautics, Imperial College London (UK), and Scientific
12 // Computing and Imaging Institute, University of Utah (USA).
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Csv IO
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
37 
38 #include <boost/algorithm/string.hpp>
39 #include <boost/tokenizer.hpp>
40 
41 #include <fstream>
42 #include <vector>
43 
44 #include <boost/format.hpp>
45 
46 #ifdef NEKTAR_USE_MPI
47 #include <mpi.h>
48 #endif
49 
50 #include "ErrorUtil.hpp"
53 
54 namespace Nektar
55 {
56 namespace LibUtilities
57 {
58 
59 CsvIO::CsvIO(CommSharedPtr pComm, bool sharedFilesystem)
60  : PtsIO(pComm, sharedFilesystem)
61 {
62 }
63 
64 /**
65  * @brief Save a pts field to a file
66  *
67  * @param outFile filename of the file
68  * @param ptsField the pts field
69  */
70 void CsvIO::Write(const std::string &outFile,
72  const bool backup)
73 {
74  size_t nTotvars = ptsField->GetNFields() + ptsField->GetDim();
75  size_t np = ptsField->GetNpoints();
76 
77  std::string filename = SetUpOutput(outFile, true, backup);
78  SetUpFieldMetaData(outFile);
79 
80  std::ofstream ptsFile;
81  ptsFile.open(filename.c_str());
82 
83  std::vector<std::string> xyz;
84  xyz.push_back("x");
85  xyz.push_back("y");
86  xyz.push_back("z");
87  xyz.resize(ptsField->GetDim());
88 
89  std::string fn = boost::algorithm::join(xyz, ",");
90  ptsFile << "# " << fn << ",";
91  fn = boost::algorithm::join(ptsField->GetFieldNames(), ",");
92  ptsFile << fn;
93  ptsFile << std::endl;
94 
96  ptsField->GetPts(pts);
97  for (size_t i = 0; i < np; ++i)
98  {
99  ptsFile << pts[0][i];
100  for (size_t j = 1; j < nTotvars; ++j)
101  {
102  ptsFile << "," << pts[j][i];
103  }
104  ptsFile << std::endl;
105  }
106 
107  ptsFile.close();
108 }
109 
110 void CsvIO::v_ImportFieldData(const std::string inFile,
111  PtsFieldSharedPtr &ptsField,
112  DomainRangeShPtr &Range)
113 {
114  std::stringstream errstr;
115  errstr << "Unable to load file: " << inFile << std::endl;
116  std::ifstream in(inFile.c_str());
117  ASSERTL0(in.is_open(), errstr.str());
118 
119  std::string line;
120  std::getline(in, line);
121  boost::erase_first(line, "#");
122 
123  std::vector<std::string> fieldNames;
124  bool valid = ParseUtils::GenerateVector(line, fieldNames);
125  ASSERTL0(valid, "Unable to process list of fields from line: " + line);
126 
127  int dim = 0;
128  for (auto &it : fieldNames)
129  {
130  if (it == "x" || it == "y" || it == "z")
131  {
132  dim++;
133  }
134  }
135 
136  ASSERTL0(dim, "Failed to find a paramater labelled \"x\",\"y\" or \"z\" "
137  "in file" +
138  inFile + ". Is the coordinated labelled something else?");
139 
140  size_t totvars = fieldNames.size();
141  std::vector<std::string> dimNames = {"x", "y", "z"};
142  Array<OneD, int> loc_coord(dim);
143  for (int i = 0; i < dim; ++i)
144  {
145  auto p = std::find(fieldNames.begin(), fieldNames.end(), dimNames[i]);
146  if (p != fieldNames.end())
147  {
148  auto j = std::distance(fieldNames.begin(), p);
149 
150  loc_coord[i] = j;
151  }
152  }
153 
154  std::vector<NekDouble> ptsSerial;
155  typedef boost::tokenizer<boost::escaped_list_separator<char>> Tokenizer;
156  Tokenizer tok(line);
157  while (getline(in, line))
158  {
159  tok.assign(line);
160 
161  ASSERTL0(std::distance(tok.begin(), tok.end()) ==
162  std::iterator_traits<Tokenizer::iterator>::difference_type(
163  totvars),
164  "wrong number of columns in line: " + line);
165 
166  bool ReadValue = true;
167 
168  if (Range != NullDomainRangeShPtr)
169  {
170  int cnt = 0;
171  for (auto &it : tok)
172  {
173  for (int j = 0; j < dim; ++j)
174  {
175  if (cnt == loc_coord[j])
176  {
177  NekDouble CoordVal = boost::lexical_cast<NekDouble>(
178  boost::trim_copy(std::string(it)));
179  switch (j)
180  {
181  case 0:
182  {
183  if ((CoordVal < Range->m_xmin) ||
184  (CoordVal > Range->m_xmax))
185  {
186  ReadValue = false;
187  }
188  }
189  break;
190  case 1:
191  {
192  if ((CoordVal < Range->m_ymin) ||
193  (CoordVal > Range->m_ymax))
194  {
195  ReadValue = false;
196  }
197  }
198  break;
199  case 2:
200  {
201  if ((CoordVal < Range->m_zmin) ||
202  (CoordVal > Range->m_zmax))
203  {
204  ReadValue = false;
205  }
206  }
207  }
208  }
209  }
210  cnt++;
211  }
212  }
213  if (ReadValue)
214  {
215  for (auto &it : tok)
216  {
217  try
218  {
219  ptsSerial.push_back(boost::lexical_cast<NekDouble>(
220  boost::trim_copy(std::string(it))));
221  }
222  catch (const boost::bad_lexical_cast &)
223  {
225  "could not convert line: " + line);
226  }
227  }
228  }
229  }
230 
231  size_t npts = ptsSerial.size() / totvars;
232 
234  for (size_t i = 0; i < totvars; ++i)
235  {
236  pts[i] = Array<OneD, NekDouble>(npts);
237  }
238 
239  for (size_t i = 0; i < npts; ++i)
240  {
241  for (size_t j = 0; j < totvars; ++j)
242  {
243  pts[j][i] = ptsSerial[i * totvars + j];
244  }
245  }
246 
247  // reorder pts to make x,y,z the first columns
248  for (int i = 0; i < dim; ++i)
249  {
250  auto p = std::find(fieldNames.begin(), fieldNames.end(), dimNames[i]);
251  if (p != fieldNames.end())
252  {
253  auto j = std::distance(fieldNames.begin(), p);
254 
255  if (i == j)
256  {
257  continue;
258  }
259 
260  Array<OneD, NekDouble> tmp = pts[i];
261  pts[i] = pts[j];
262  pts[j] = tmp;
263 
264  std::string tmp2 = fieldNames[i];
265  fieldNames[i] = fieldNames[j];
266  fieldNames[j] = tmp2;
267  }
268  }
269  fieldNames.erase(fieldNames.begin(), fieldNames.begin() + dim);
270 
271  ptsField = MemoryManager<PtsField>::AllocateSharedPtr(dim, fieldNames, pts);
272 }
273 
274 std::string CsvIO::v_GetFileEnding() const
275 {
276  return "csv";
277 }
278 
279 } // namespace LibUtilities
280 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
void Write(const std::string &outFile, const PtsFieldSharedPtr &ptsField, const bool backup=false)
Save a pts field to a file.
Definition: CsvIO.cpp:70
virtual void v_ImportFieldData(const std::string inFile, PtsFieldSharedPtr &ptsField, DomainRangeShPtr &Range) override
Definition: CsvIO.cpp:110
virtual std::string v_GetFileEnding() const override
Definition: CsvIO.cpp:274
CsvIO(LibUtilities::CommSharedPtr pComm, bool sharedFilesystem=false)
Definition: CsvIO.cpp:59
std::string SetUpOutput(const std::string outname, bool perRank, bool backup=false)
Set up the filesystem ready for output.
Definition: FieldIO.cpp:406
void SetUpFieldMetaData(const std::string outname)
Definition: PtsIO.cpp:306
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
static bool GenerateVector(const std::string &str, std::vector< T > &out)
Takes a comma-separated string and converts it to entries in a vector.
Definition: ParseUtils.cpp:131
std::shared_ptr< PtsField > PtsFieldSharedPtr
Definition: PtsField.h:190
std::shared_ptr< DomainRange > DomainRangeShPtr
Definition: DomainRange.h:66
static DomainRangeShPtr NullDomainRangeShPtr
Definition: DomainRange.h:67
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:54
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:444
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble