Peano
Loading...
Searching...
No Matches
PeanoTextPatchFileReader.cpp
Go to the documentation of this file.
1#include <string>
2#include <iostream>
3#include <vector>
4#include <fstream>
5
6
7#include "Parser.h"
9
10
11#include "tarch/Assertions.h"
13
15#include "tarch/mpi/Rank.h"
16
17
18tarch::logging::Log convert::input::PeanoTextPatchFileReader::_log( "convert::input::PeanoTextPatchFileReader" );
19
20
22 _file(file),
23 _dimensions(-1) {
24}
25
26
29
30
32 int result = -1;
33 const std::string prefix = "tree";
34 const std::string separator = "-";
35 std::size_t start = _file.find( "tree" + separator );
36 if (start != std::string::npos) {
37 start += std::string("tree" + separator).length();
38 std::size_t end = _file.find( separator, start );
39 std::string identifier = _file.substr( start, end-start );
40 result = std::atoi( identifier.c_str() );
41 }
42 return result;
43}
44
45
47 logInfo( "parse()", "reading file " << _file );
48
49 bool isFirstDataSet = true;
50
51 std::vector< PeanoTextPatchFileReader > subReaders;
52
53 // Push in default guy
54 _data.push_back( convert::data::DataSet() );
55
56 std::ifstream ifs(_file);
57 std::vector<std::string> lines;
58 for (std::string line; std::getline(ifs, line); ) {
59 lines.push_back(line);
60 }
61 ifs.close();
62
63 if (lines.empty()) {
64 logError( "parse()", "file " << _file << " is empty (or does not exist)" );
65 }
66
67 int treeNumber = extractTreeNumberFromFileName();
68 logDebug( "parse()", "file " << _file << " will yield data with tree number " << treeNumber );
69
70 {
71 for(uint i = 0; i < lines.size(); i++) {
72 std::string line = lines[i];
73
74 std::vector< std::string > tokens = Parser::tokenise( line );
75
76 if( tokens.empty()) { // or tokens[0]=="#" ) {
77 }
78 else if ( tokens[0]=="begin" and tokens[1]=="dataset" ) { //new snapshot
79 if (_data.size()==1 and isFirstDataSet) {
80 logInfo( "parse()", "data file is meta file including multiple data sets");
81 isFirstDataSet = false;
82 }
83 else {
84 _data.push_back( convert::data::DataSet() );
85 }
86 }
87 else if ( tokens[0]=="end" and tokens[1]=="dataset" ) { //new snapshot
88 const int NumberOfSubreaders = subReaders.size();
89 #pragma omp parallel for
90 for (int i=0; i<NumberOfSubreaders; i++) {
91 subReaders[i].parse();
92 std::vector< convert::data::DataSet > subData = subReaders[i].getData();
93
94 if ( subData.size()>1 ) {
95 logError( "parse()", "included dataset seems to hold more than one dataset, i.e. seems to be series of datasets again. This is not supported" );
96 }
97
98 if ( not subData.empty() ) {
99 #pragma omp critical
100 {
101 _data.back().merge( subData[0] );
102 }
103 }
104 }
105
106 // will be reused for next dataset if this is a series of datasets
107 subReaders.clear();
108 }
109 else if ( tokens[0]=="include") {
110 std::string directory = Parser::getDirectory(_file);
111 if ( directory.empty() ) directory = ".";
112 const std::string filename = directory + "/" + Parser::removeHyphens(tokens[1]);
113
114 logInfo ( "parse()", "create a new reader (with new task) for file " << filename << " resulting from token " << tokens[1] );
115
116 subReaders.push_back( PeanoTextPatchFileReader(filename) );
117 }
118 else if ( tokens[0]=="begin" and tokens[1]=="cell-metadata" ) { //define a cell variable
119 std::string variableName = Parser::removeHyphens(tokens[2]);
120 std::vector<std::string> variableDeclarationLines;
121 while ( i<lines.size() and lines[i].find( "end cell-metadata" )==std::string::npos ) {
122 variableDeclarationLines.push_back( lines[i] );
123 i++;
124 }
125 if (i==lines.size()) {
126 logError( "parse()", "file " << _file << " is corrupt as cell-metadata for " << variableName << " is not terminated properly. Quit parsing" );
128 }
129 else {
130 parseVariablesDeclaration( _data.size()-1, variableDeclarationLines, variableName, convert::data::PeanoDataType::Cell_Values );
131 }
132 }
133 else if ( tokens[0]=="begin" and tokens[1]=="vertex-metadata" ) { //define a vertex variable
134 std::string variableName = Parser::removeHyphens(tokens[2]);
135 std::vector<std::string> variableDeclarationLines;
136 while ( i<lines.size() and lines[i].find( "end vertex-metadata" )==std::string::npos ) {
137 variableDeclarationLines.push_back( lines[i] );
138 i++;
139 }
140 if (i==lines.size()) {
141 logError( "parse()", "file " << _file << " is corrupt as vertex-metadata for " << variableName << " is not terminated properly. Quit parsing" );
143 }
144 else {
145 parseVariablesDeclaration( _data.size()-1, variableDeclarationLines, variableName, convert::data::PeanoDataType::Vertex_Values );
146 }
147 }
148 else if ( tokens[0]=="dimensions" ) {
149 try {
150 _dimensions = std::stoi(tokens[1]);
151 }
152 catch (std::out_of_range& e) {
153 logError( "parse()", "error reading data for data set for _dimensions" );
154 logError( "parse()", "invalid token: " << tokens[1] );
155 logError( "parse()", "have to quit" );
157 }
158 logDebug( "parse()", "dimensions=" << _dimensions );
159 }
160 else if( tokens[0]=="begin" and tokens[1]=="patch" ) {
161 logDebug( "parse()", "start to parse patch" );
162 std::vector<std::string> patchLines;
163 while ( i<lines.size() and lines[i].find( "end patch" )==std::string::npos ) {
164 patchLines.push_back( lines[i] );
165 i++;
166 }
167 if (i==lines.size()) {
168 logError( "parse()", "file " << _file << " is corrupt as begin patch is not terminated properly. Quit parsing" );
169 }
170 else {
171 parsePatch( _data.size()-1, treeNumber, patchLines );
172 }
173 }
174 else {
175 logDebug( "parse()", "ignore line " << line );
176 }
177 }} // OpenMP and for loop scope
178
179 if (_data.size()>1) {
180 logDebug( "parse()", "file " << _file << " hosts " << _data.size() << " data sets (time steps or iterations, e.g.)");
181 }
182 else {
183 logDebug( "parse()", "file " << _file << " hosts " << _data[0].data.size() << " variable(s)");
184 for (auto p: _data[0].data) {
185 logDebug( "parse()", "variable " << p.first.name << " is held by " << p.second.size() << " patch(es)");
186 }
187 }
188}
189
190
191void convert::input::PeanoTextPatchFileReader::parseVariablesDeclaration( int dataSetCounter, const std::vector<std::string>& description, const std::string& variableName, convert::data::PeanoDataType type ) {
192 //get mapping
193 int numberOfUnknowns = -1;
194 int numberOfDofs = -1;
195 for (auto p: description) {
196 std::vector<std::string> tokens = Parser::tokenise( p );
197 if (tokens[0]=="number-of-unknowns") {
198 try {
199 numberOfUnknowns = std::stoi(tokens[1]);
200 }
201 catch (std::out_of_range& e) {
202 logError( "parse()", "error reading data for data set for number-of-unknowns" );
203 logError( "parse()", "invalid token: " << tokens[1] );
204 logError( "parse()", "have to quit" );
206 }
207 }
208 if (tokens[0]=="number-of-dofs-per-axis") {
209 try {
210 numberOfDofs = std::stoi(tokens[1]);
211 }
212 catch (std::out_of_range& e) {
213 logError( "parse()", "error reading data for data set for number-of-dofs-per-axis" );
214 logError( "parse()", "invalid token: " << tokens[1] );
215 logError( "parse()", "have to quit" );
217 }
218 }
219 }
220
221/*
222 double* mapping = nullptr;
223 int mappings = -1;
224 std::string line2 = lines[i+2];
225 if( line2.compare( "begin mapping")==0 ) {
226 logDebug( "parse()", "start to parse mapping" );
227 std::vector<std::string> patchLines;
228 while ( lines[i].find( "end mapping" )==std::string::npos ) {
229 patchLines.push_back( lines[i] );
230 i++;
231 }
232 mapping = parseMapping( patchLines );
233 }
234 _data.push
235*/
236
237 // @todo This belongs into the variable definition
238/*
239 else if( tokens[0]=="patch-size" ) {
240 for(int j = 1; j <= dimensions; j++) {
241 patchSize[j-1] = std::stoi(tokens[j]);
242 }
243
244 //update number of cells and vertices
245 cells = 1;
246 vertices = 1;
247 for(int i = 0; i < dimensions; i++) {
248 cells *= patchSize[i];
249 vertices *= patchSize[i] +1;
250 }
251 }
252*/
253
254 logDebug( "parse()", "added new variables " << variableName << " with " << numberOfDofs << " dof per axis (Cartesian layout) and " << numberOfUnknowns << " unknowns per dof" );
255
256 if (numberOfUnknowns<=0) {
257 logError( "parseVariablesDeclaration(int,...)", "corrupted data file " << _file << " as number-of-unknowns for " << variableName << " is smaller or equal to 0. Terminate parsing" );
258 }
259 else if (numberOfDofs<=0) {
260 logError( "parseVariablesDeclaration(int,...)", "corrupted data file " << _file << " as number-of-dofs-per-axis for " << variableName << " is smaller or equal to 0. Terminate parsing" );
261 return;
262 }
263 else {
264 _data[dataSetCounter].data.insert(
265 std::pair<convert::data::Variable, std::vector<convert::data::PatchData>>(
266 convert::data::Variable( variableName, numberOfDofs, numberOfUnknowns, type, _dimensions ),
267 std::vector<convert::data::PatchData>()
268 )
269 );
270 }
271}
272
273
274/*
275double* convert::input::PeanoTextPatchFileReader::parseMapping( const std::vector<std::string>& patchDescription ) {
276 std::vector<double> data;
277 for (auto p: patchDescription) {
278 std::vector<std::string> tokens = Parser::tokenise(p);
279 for (auto pp: tokens) {
280 data.push_back( std::stod(pp) );
281 }
282 }
283 double* result = new double[ data.size() ];
284 for (int i=0; i<data.size(); i++) {
285 result[i] = data[i];
286 }
287 return result;
288}
289*/
290
291
292void convert::input::PeanoTextPatchFileReader::parsePatch( int dataSetCounter, int treeNumber, const std::vector<std::string>& text ) {
293 assertion( _dimensions==2 or _dimensions==3 );
294
295 logDebug( "parsePatch(...)", "create patch described by " << text.size() << " lines" );
296
297 std::vector<double> offset;
298 std::vector<double> size;
299
300 for (int i=0; i<text.size(); i++) {
301 std::vector<std::string> tokens = Parser::tokenise( text[i] );
302
303 if( tokens[0]=="offset" ) {
304 logDebug( "parsePatch(...)", "set offset to " << text[i] );
305 for(int j = 0; j < _dimensions; j++) {
306 try {
307 offset.push_back( std::stod(tokens[j+1]) );
308 }
309 catch (std::out_of_range& e) {
310 logError( "parsePatch(...)", "error reading data for data set " << dataSetCounter );
311 logError( "parsePatch(...)", "invalid token: " << tokens[j+1] );
312 logError( "parsePatch(...)", "have to quit" );
314 }
315 }
316 }
317 else if ( tokens[0]=="size" ) {
318 logDebug( "parsePatch(...)", "set sizes to " << text[i] );
319 for(int j = 0; j < _dimensions; j++) {
320 try {
321 size.push_back( std::stod(tokens[j+1]) );
322 }
323 catch (std::out_of_range& e) {
324 logError( "parsePatch(...)", "error reading data for data set " << dataSetCounter );
325 logError( "parsePatch(...)", "invalid token: " << tokens[j+1] );
326 logError( "parsePatch(...)", "have to quit" );
328 }
329 }
330 }
331 else if ( tokens[0]=="begin" and tokens[1]=="cell-values") {
332 std::string variableName = Parser::removeHyphens(tokens[2]);
333
334 i++;
335 std::vector<std::string> data;
336 while ( i<text.size() and text[i].find( "end cell-values" )==std::string::npos ) {
337 std::vector<std::string> tokens = Parser::tokenise( text[i] );
338 data.insert( data.end(), tokens.begin(), tokens.end() );
339 i++;
340 }
341
342 if (i==text.size()) {
343 logError( "parsePatch()", "file " << _file << " is corrupt as begin cell-values is not terminated properly. Quit parsing" );
344 }
345 else {
346 logDebug( "parsePatch(...)", "found " << data.size() << " entries for " << variableName );
347 addDataToPatch(dataSetCounter,variableName,offset.data(),size.data(),treeNumber,data);
348 }
349 }
350 else if ( tokens[0]=="begin" and tokens[1]=="vertex-values" ) {
351 std::string variableName = Parser::removeHyphens(tokens[2]);
352
353 i++;
354 std::vector<std::string> data;
355 while ( i<text.size() and text[i].find( "end vertex-values" )==std::string::npos ) {
356 std::vector<std::string> tokens = Parser::tokenise( text[i] );
357 data.insert( data.end(), tokens.begin(), tokens.end() );
358 i++;
359 }
360 if (i==text.size()) {
361 logError( "parsePatch()", "file " << _file << " is corrupt as begin vertex-values is not terminated properly. Quit parsing" );
362 }
363 else {
364 addDataToPatch(dataSetCounter,variableName,offset.data(),size.data(),treeNumber,data);
365 }
366 }
367 }
368}
369
370
371void convert::input::PeanoTextPatchFileReader::addDataToPatch( int dataSetCounter, const std::string& variableName, double* offset, double* size, int treeNumber, const std::vector< std::string >& textData ) {
372 logDebug( "parsePatch(...)", "set data of variable " << variableName << " (parse " << textData.size() << " entries)");
373
374 if (!_data[dataSetCounter].hasVariable(variableName)) {
375 logError( "parsePatch(...)", "no variables for " << variableName << " have been declared. Ignore data set");
376 return;
377 }
378
379 const convert::data::Variable key = _data[dataSetCounter].getVariable(variableName);
380
381 const int expectedDataEntries = key.getTotalNumberOfQuantitiesPerPatch();
382 if ( textData.size()!=expectedDataEntries ) {
383 logError( "parsePatch(...)", "expected " << expectedDataEntries << " data entries for variable " << variableName << " but got " << textData.size() << ". Ignore data set. Key=" << key.toString() );
384 return;
385 }
386
387 convert::data::PatchData newEntry(_dimensions, offset, size, key.dofsPerAxis, key.unknowns, treeNumber);
388 for (int i=0; i<expectedDataEntries; i++) {
389 try {
390 newEntry.data[i] = std::stod(textData[i]);
391 }
392 catch (std::out_of_range& e) {
393 logError( "parsePatch(...)", "error reading data for " << variableName );
394 logError( "parsePatch(...)", "invalid value: " << textData[i] );
395 logError( "parsePatch(...)", "have to quit" );
397 }
398 }
399
400 _data[dataSetCounter].data[key].push_back( newEntry );
401}
402
403
404
405std::vector< convert::data::DataSet > convert::input::PeanoTextPatchFileReader::getData() const {
406 return _data;
407}
#define assertion(expr)
#define logError(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:464
#define logDebug(methodName, logMacroMessageStream)
Definition Log.h:50
#define logInfo(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:411
A dataset is a wrapper around one big map.
Definition DataSet.h:34
A patch is a square or cube in the domain.
Definition PatchData.h:25
double * data
Mapping from variables onto the actual data.
Definition PatchData.h:54
Represents one variable that is subsequently attached to the patches of a file.
Definition Variable.h:18
const int unknowns
If this unknown holds 1, it is scalar, for d it is vector data, and so forth.
Definition Variable.h:30
std::string toString() const
Definition Variable.cpp:57
int getTotalNumberOfQuantitiesPerPatch() const
This is getTotalNumberOfDofsPerPatch() times the number of unknowns per dof.
Definition Variable.cpp:27
static std::string getDirectory(const std::string &fileName)
Definition Parser.cpp:20
static std::vector< std::string > tokenise(const std::string &line)
Definition Parser.cpp:7
static std::string removeHyphens(const std::string &value)
Definition Parser.cpp:25
void addDataToPatch(int dataSetCounter, const std::string &variableName, double *offset, double *size, int treeNumber, const std::vector< std::string > &textData)
void parsePatch(int dataSetCounter, int treeNumber, const std::vector< std::string > &patchDescription)
void parseVariablesDeclaration(int dataSetCounter, const std::vector< std::string > &patchDescription, const std::string &name, convert::data::PeanoDataType type)
virtual std::vector< convert::data::DataSet > getData() const override
A file can hold a series of datasets.
PeanoTextPatchFileReader(const std::string &file)
Read in one file.
Log Device.
Definition Log.h:516
static void abort(int errorCode)
A proper abort in an MPI context has to use MPI_Abort.
Definition Rank.cpp:592