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
54namespace Nektar
55{
56namespace LibUtilities
57{
58
59CsvIO::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 */
70void 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
110void 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
274std::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:57
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:453
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble