Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
vlsv2silo.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 * Copyright 2010-2016 Finnish Meteorological Institute
4 *
5 * For details of usage, see the COPYING file and read the "Rules of the Road"
6 * at http://www.physics.helsinki.fi/vlasiator/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#include <cstdlib>
24#include <iostream>
25#include <stdint.h>
26#include <cmath>
27#include <list>
28#include <silo.h>
29#include <sstream>
30#include <dirent.h>
31#include <mpi.h>
32#include <array> //std::array from here
33//#include <typeinfo>
34
35#include "vlsv_reader.h"
36#include "definitions.h"
37#include "vlsvreaderinterface.h"
38
39using namespace std;
40
41
42//A struct for holding info on cell structure (the grid)
44 //The number of cells in x, y, z direction (initialized somewhere in read parameters)
45 uint64_t cell_bounds[3];
46 //Length of a cell in x, y, z direction
48 //x_min, y_min, z_min are stored here
50
51 //The number of cells in x, y, z direction (initialized somewhere in read parameters)
52 uint64_t vcell_bounds[3];
53 //Length of a cell in x, y, z direction
55 //vx_min, vy_min, vz_min are stored here
57};
58
59
60using namespace vlsv;
61
62//Calculates the cell coordinates and outputs into coordinates
63//Input:
64//[0] CellStructure cellStruct -- A struct for holding cell information. Has the cell length in x,y,z direction, for example
65//[1] uint64_t cellId -- Some given cell id
66//Output:
67//[0] Real * coordinates -- Some coordinates x, y, z (NOTE: the vector size should be 3!)
68void getCellCoordinates( const CellStructure & cellStruct, const uint64_t _cellId, array<Real, 3> & coordinates ) {
69 //In vlasiator the cell ids start from 1 but for fetching coordinates it's more logical to start from 0
70 const uint64_t cellId = _cellId - 1;
71 //Calculate the cell coordinates in block coordinates (so in the cell grid where the coordinates are integers)
72 uint64_t currentCellCoordinate[3];
73 //Note: cell_bounds is a variable that tells the length of a cell in x, y or z direction (depending on the index)
74 //cellStruct is a struct that holds info on the cell structure used in simulation (such as the length of the cell and the mininum
75 //value of x within the cell grid)
76 currentCellCoordinate[0] = cellId % cellStruct.cell_bounds[0];
77 currentCellCoordinate[1] = ((cellId - currentCellCoordinate[0]) / cellStruct.cell_bounds[0]) % cellStruct.cell_bounds[1];
78 currentCellCoordinate[2] = ((cellId - cellStruct.cell_bounds[0]*currentCellCoordinate[1]) / (cellStruct.cell_bounds[0]*cellStruct.cell_bounds[1]));
79 //Get the coordinates of the cell. These are the coordinates in actual space (not cell coordinates, which are integers from 1 up to some number)
80 coordinates[0] = cellStruct.min_coordinates[0] + currentCellCoordinate[0] * cellStruct.cell_length[0];
81 coordinates[1] = cellStruct.min_coordinates[1] + currentCellCoordinate[1] * cellStruct.cell_length[1];
82 coordinates[2] = cellStruct.min_coordinates[2] + currentCellCoordinate[2] * cellStruct.cell_length[2];
83 //all done
84 return;
85}
86
87//Initalizes cellStruct
88//Input:
89//[0] vlsv::Reader vlsvReader -- some reader with a file open (used for loading parameters)
90//Output:
91//[0] CellStructure cellStruct -- Holds info on cellStruct. The members are given the correct values here (Note: CellStructure could be made into a class
92//instead of a struct with this as the constructor but since a geometry class has already been coded before, it would be a waste)
93void setCellVariables( vlsvinterface::Reader & vlsvReader, CellStructure & cellStruct ) {
94 //Get x_min, x_max, y_min, y_max, etc so that we know where the given cell id is in (loadParameter returns char*, hence the cast)
95 //O: Note: Not actually sure if these are Real valued or not
96 Real x_min, x_max, y_min, y_max, z_min, z_max, vx_min, vx_max, vy_min, vy_max, vz_min, vz_max;
97 //Read in the parameter:
98 if( vlsvReader.readParameter( "xmin", x_min ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
99 if( vlsvReader.readParameter( "xmax", x_max ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
100 if( vlsvReader.readParameter( "ymin", y_min ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
101 if( vlsvReader.readParameter( "ymax", y_max ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
102 if( vlsvReader.readParameter( "zmin", z_min ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
103 if( vlsvReader.readParameter( "zmax", z_max ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
104
105 if( vlsvReader.readParameter( "vxmin", vx_min ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
106 if( vlsvReader.readParameter( "vxmax", vx_max ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
107 if( vlsvReader.readParameter( "vymin", vy_min ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
108 if( vlsvReader.readParameter( "vymax", vy_max ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
109 if( vlsvReader.readParameter( "vzmin", vz_min ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
110 if( vlsvReader.readParameter( "vzmax", vz_max ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
111
112 //Number of cells in x, y, z directions (used later for calculating where in the cell coordinates the given
113 //coordinates are) (Done in getCellCoordinates)
114 //There's x, y and z coordinates so the number of different coordinates is 3:
115 const short int NumberOfCoordinates = 3;
116 uint64_t cell_bounds[NumberOfCoordinates];
117 uint64_t vcell_bounds[NumberOfCoordinates];
118 //Get the number of velocity blocks in x,y,z direction from the file:
119 //x-direction
120 if( vlsvReader.readParameter( "vxblocks_ini", vcell_bounds[0] ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
121 //y-direction
122 if( vlsvReader.readParameter( "vyblocks_ini", vcell_bounds[1] ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
123 //z-direction
124 if( vlsvReader.readParameter( "vzblocks_ini", vcell_bounds[2] ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
125 //Get the number of cells in x,y,z direction from the file:
126 //x-direction
127 if( vlsvReader.readParameter( "xcells_ini", cell_bounds[0] ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
128 //y-direction
129 if( vlsvReader.readParameter( "ycells_ini", cell_bounds[1] ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
130 //z-direction
131 if( vlsvReader.readParameter( "zcells_ini", cell_bounds[2] ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
132 //Now we have the needed variables, so let's calculate how much in one block equals in length:
133 //Total length of x, y, z:
134 Real x_length = x_max - x_min;
135 Real y_length = y_max - y_min;
136 Real z_length = z_max - z_min;
137
138 Real vx_length = vx_max - vx_min;
139 Real vy_length = vy_max - vy_min;
140 Real vz_length = vz_max - vz_min;
141 //Set the cell structure properly:
142 for( int i = 0; i < NumberOfCoordinates; ++i ) {
143 cellStruct.cell_bounds[i] = cell_bounds[i];
144 cellStruct.vcell_bounds[i] = vcell_bounds[i];
145 }
146 //Calculate the cell length
147 cellStruct.cell_length[0] = ( x_length / (Real)(cell_bounds[0]) );
148 cellStruct.cell_length[1] = ( y_length / (Real)(cell_bounds[1]) );
149 cellStruct.cell_length[2] = ( z_length / (Real)(cell_bounds[2]) );
150 //Calculate the velocity cell length
151 cellStruct.vblock_length[0] = ( vx_length / (Real)(vcell_bounds[0]) );
152 cellStruct.vblock_length[1] = ( vy_length / (Real)(vcell_bounds[1]) );
153 cellStruct.vblock_length[2] = ( vz_length / (Real)(vcell_bounds[2]) );
154 //Calculate the minimum coordinates
155 cellStruct.min_coordinates[0] = x_min;
156 cellStruct.min_coordinates[1] = y_min;
157 cellStruct.min_coordinates[2] = z_min;
158 //Calculate the minimum coordinates for velocity cells
159 cellStruct.min_vcoordinates[0] = vx_min;
160 cellStruct.min_vcoordinates[1] = vy_min;
161 cellStruct.min_vcoordinates[2] = vz_min;
162
163
164 for( int i = 0; i < 3; ++i ) {
165 if( cellStruct.cell_length[i] == 0 || cellStruct.cell_bounds[i] == 0 || cellStruct.vblock_length[i] == 0 || cellStruct.vcell_bounds[i] == 0 ) {
166 cerr << "ERROR, ZERO CELL LENGTH OR CELL_BOUNDS AT " << __FILE__ << " " << __LINE__ << endl;
167 exit(1);
168 }
169 }
170 return;
171}
172//
173
174
175static DBfile* fileptr = NULL; // Pointer to file opened by SILO
176
177
178bool isDataTypeUint( vlsv::datatype::type& dataType ) {
179 if( dataType == vlsv::datatype::type::UINT ) {
180 return true;
181 } else {
182 return false;
183 }
184}
185
186template <typename T>
187uint64_t convUInt(const char* ptr,const T& dataType,const uint64_t& dataSize) {
188 if ( isDataTypeUint(dataType) == false ) {
189 cerr << "Erroneous datatype given to convUInt" << endl;
190 exit(1);
191 }
192
193 switch (dataSize) {
194 case 1:
195 return *reinterpret_cast<const unsigned char*>(ptr);
196 break;
197 case 2:
198 return *reinterpret_cast<const unsigned short int*>(ptr);
199 break;
200 case 4:
201 return *reinterpret_cast<const unsigned int*>(ptr);
202 break;
203 case 8:
204 return *reinterpret_cast<const unsigned long int*>(ptr);
205 break;
206 }
207 return 0;
208}
209
210
211int SiloType(const datatype::type & dataType, const uint64_t & dataSize) {
212 switch (dataType) {
213 case datatype::type::INT:
214 if (dataSize == 2) return DB_SHORT;
215 else if (dataSize == 4) return DB_INT;
216 else if (dataSize == 8) return DB_LONG;
217 else return -1;
218 break;
219 case datatype::type::UINT:
220 if (dataSize == 2) return DB_SHORT;
221 else if (dataSize == 4) return DB_INT;
222 else if (dataSize == 8) return DB_LONG;
223 else return -1;
224 break;
225 case datatype::type::FLOAT:
226 if (dataSize == 4) return DB_FLOAT;
227 else if (dataSize == 8) return DB_DOUBLE;
228 else return -1;
229 break;
230 case datatype::type::UNKNOWN:
231 cerr << "INVALID DATATYPE AT " << __FILE__ << " " << __LINE__ << endl;
232 exit(1);
233 }
234 return -1;
235}
236
237
238template<typename REAL> struct NodeCrd {
239 static REAL EPS;
240 REAL x;
241 REAL y;
242 REAL z;
243 NodeCrd(const REAL& x,const REAL& y,const REAL& z): x(x),y(y),z(z) { }
244
245 bool comp(const NodeCrd<REAL>& n) const {
246 REAL EPS1,EPS2,EPS;
247 EPS1 = 1.0e-6 * fabs(x);
248 EPS2 = 1.0e-6 * fabs(n.x);
249 if (x == 0.0) EPS1 = 1.0e-7;
250 if (n.x == 0.0) EPS2 = 1.0e-7;
251 EPS = max(EPS1,EPS2);
252 if (fabs(x - n.x) > EPS) return false;
253
254 EPS1 = 1.0e-6 * fabs(y);
255 EPS2 = 1.0e-6 * fabs(n.y);
256 if (y == 0.0) EPS1 = 1.0e-7;
257 if (n.y == 0.0) EPS2 = 1.0e-7;
258 EPS = max(EPS1,EPS2);
259 if (fabs(y - n.y) > EPS) return false;
260
261 EPS1 = 1.0e-6 * fabs(z);
262 EPS2 = 1.0e-6 * fabs(n.z);
263 if (z == 0.0) EPS1 = 1.0e-7;
264 if (n.z == 0.0) EPS2 = 1.0e-7;
265 EPS = max(EPS1,EPS2);
266 if (fabs(z - n.z) > EPS) return false;
267 return true;
268 }
269};
270
271struct NodeComp {
272 bool operator()(const NodeCrd<double>& a,const NodeCrd<double>& b) const {
273 if (a.comp(b) == true) return false;
274 double EPS = 0.5e-5 * (fabs(a.z) + fabs(b.z));
275 if (a.z > b.z + EPS) return false;
276 if (a.z < b.z - EPS) return true;
277
278 EPS = 0.5e-5 * (fabs(a.y) + fabs(b.y));
279 if (a.y > b.y + EPS) return false;
280 if (a.y < b.y - EPS) return true;
281
282 EPS = 0.5e-5 * (fabs(a.x) + fabs(b.x));
283 if (a.x > b.x + EPS) return false;
284 if (a.x < b.x - EPS) return true;
285 //cerr << "ERROR" << endl;
286 return false;
287 }
288
289 bool operator()(const NodeCrd<float>& a,const NodeCrd<float>& b) const {
290 if (a.comp(b) == true) return false;
291 float EPS = 0.5e-5 * (fabs(a.z) + fabs(b.z));
292 if (a.z > b.z + EPS) return false;
293 if (a.z < b.z - EPS) return true;
294
295 EPS = 0.5e-5 * (fabs(a.y) + fabs(b.y));
296 if (a.y > b.y + EPS) return false;
297 if (a.y < b.y - EPS) return true;
298
299 EPS = 0.5e-5 * (fabs(a.x) + fabs(b.x));
300 if (a.x > b.x + EPS) return false;
301 if (a.x < b.x - EPS) return true;
302 //cerr << "ERROR" << endl;
303 return false;
304 }
305};
306
307
308//Function for converting a mesh variable (Saves the variable into an open SILO file)
309//Input:
310//[0] vlsvReader -- some vlsv reader with a file open
311//[1] meshName -- name of the mesh, e.g. "SpatialGrid"
312//[2] varName -- Name of the variable
313template <class T>
314bool convertMeshVariable(T & vlsvReader,const string& meshName,const string& varName) {
315 bool success = true;
316
317 // Writing a unstructured grid variable is a rather straightforward process. The
318 // only compilation here is that some of the variables are actually vectors, i.e.
319 // vectorSize > 1 (vectorSize == 1 for scalars). Format in which vectors are stored in VLSV
320 // differ from format in which they are written to SILO files.
321 vlsv::datatype::type dataType;
322 uint64_t arraySize,vectorSize,dataSize;
323 list<pair<string, string> > xmlAttributes;
324 xmlAttributes.push_back(make_pair("name", varName));
325 xmlAttributes.push_back(make_pair("mesh", meshName));
326 if (vlsvReader.getArrayInfo("VARIABLE", xmlAttributes, arraySize, vectorSize, dataType, dataSize) == false) return false;
327 // Read variable data. Note that we do not actually need to care if
328 // the data is given as floats or doubles.
329 char* buffer = new char[arraySize*vectorSize*dataSize];
330 const short unsigned int startingIndex = 0;
331 if (vlsvReader.readArray("VARIABLE", xmlAttributes, startingIndex, arraySize, buffer ) == false) success = false;
332 if (success == false) {
333 cerr << "FAILED TO READ VARIABLE AT " << __FILE__ << " " << __LINE__ << endl;
334 delete[] buffer;
335 return success;
336 }
337
338 // Vector variables need to be copied to temporary arrays before
339 // writing to SILO file:
340 char** components = new char*[vectorSize];
341 for (uint64_t i=0; i<vectorSize; ++i) {
342 components[i] = new char[arraySize*dataSize];
343 for (uint64_t j=0; j<arraySize; ++j) for (uint64_t k=0; k<dataSize; ++k)
344 components[i][j*dataSize+k] = buffer[j*vectorSize*dataSize + i*dataSize + k];
345 }
346
347 // SILO requires one variable name per (vector) component, but we only have one.
348 // That is, for electric field SILO would like to get "Ex","Ey", and "Ez", but we
349 // only have "E" in VLSV file. Use the VLSV variable name for all components.
350 vector<string> varNames(vectorSize);
351 vector<char*> varNamePtrs(vectorSize);
352 for (uint64_t i=0; i<vectorSize; ++i) {
353 stringstream ss;
354 ss << varName << (i+1);
355 varNames[i] = ss.str();
356 varNamePtrs[i] = const_cast<char*>(varNames[i].c_str());
357 }
358
359 // Write the unstructured mesh variable to SILO.
360 if (DBPutUcdvar(fileptr,varName.c_str(),meshName.c_str(),vectorSize,&(varNamePtrs[0]),components,arraySize,NULL,0,SiloType(dataType,dataSize),DB_ZONECENT,NULL) < 0) success = false;
361
362 for (uint64_t i=0; i<vectorSize; ++i) {
363 delete [] components[i];
364 }
365 delete [] components;
366 delete [] buffer;
367 return success;
368}
369
370
371
372
373bool convertMesh(vlsvinterface::Reader & vlsvReader,const string& meshName) {
374 bool success = true;
375 const float EPS = 1.0e-7;
376
377 // First task is to push all unique node coordinates into a map.
378 // This is not too difficult for unrefined grids, since each spatial cell stores
379 // its bottom lower left corner coordinate and size. For refined grid the situation
380 // is more complex, as there are more unique nodes than the lower left corners:
381 map<NodeCrd<Real>,uint64_t,NodeComp> nodes;
382
383 //Read in all cell ids:
384 vector<uint64_t> cellIds;
385 if( vlsvReader.getCellIds( cellIds ) == false ) {
386 cerr << "Failed to read cell ids at " << __FILE__ << " " << __LINE__ << endl;
387 return false;
388 }
389
390 //Read in cell structure (Used in calculating coordinates from cell ids)
391 CellStructure cellStruct;
392 setCellVariables( vlsvReader, cellStruct );
393
394 // Read the coordinate array one node (of a spatial cell) at a time
395 // and create a map which only contains each existing node once.
396 //char* coordsBuffer = new char[vectorSize*dataSize];
397 //Real* ptr = reinterpret_cast<Real*>(coordsBuffer);
398 //for (uint64_t i=0; i<arraySize; ++i) {
399 int i = 0;
400 for( vector<uint64_t>::const_iterator it = cellIds.begin(); it != cellIds.end(); ++it, ++i ) {
401 //if (vlsvReader.readArray("COORDS",meshName,i,1,coordsBuffer) == false) {success = false; break;}
402
403 // Insert all eight nodes of a cell into map nodes.
404 // NOTE: map is a unique associative container - given a suitable comparator, map
405 // will filter out duplicate nodes.
406 //Get cell coordinates:
407 const uint64_t cellId = *it;
408 array<Real, 3> coordinates;
409 //Store the coordinates in 'coordinates' std::array
410 getCellCoordinates( cellStruct, cellId, coordinates );
411
412 //Note: cellStruct.cell_length[i] = a cell's length in i direction
413 Real X0 = coordinates[0];
414 Real X1 = coordinates[0]+cellStruct.cell_length[0];
415 Real Y0 = coordinates[1];
416 Real Y1 = coordinates[1]+cellStruct.cell_length[1];
417 Real Z0 = coordinates[2];
418 Real Z1 = coordinates[2]+cellStruct.cell_length[2];
419
420 // Flush very small coordinate values to zero:
421 if (fabs(X0) < EPS) X0 = 0.0;
422 if (fabs(X1) < EPS) X1 = 0.0;
423 if (fabs(Y0) < EPS) Y0 = 0.0;
424 if (fabs(Y1) < EPS) Y1 = 0.0;
425 if (fabs(Z0) < EPS) Z0 = 0.0;
426 if (fabs(Z1) < EPS) Z1 = 0.0;
427
428 nodes.insert(make_pair(NodeCrd<Real>(X0,Y0,Z0),0));
429 nodes.insert(make_pair(NodeCrd<Real>(X1,Y0,Z0),0));
430 nodes.insert(make_pair(NodeCrd<Real>(X1,Y1,Z0),0));
431 nodes.insert(make_pair(NodeCrd<Real>(X0,Y1,Z0),0));
432 nodes.insert(make_pair(NodeCrd<Real>(X0,Y0,Z1),0));
433 nodes.insert(make_pair(NodeCrd<Real>(X1,Y0,Z1),0));
434 nodes.insert(make_pair(NodeCrd<Real>(X1,Y1,Z1),0));
435 nodes.insert(make_pair(NodeCrd<Real>(X0,Y1,Z1),0));
436 }
437 if (success == false) {
438 cerr << "ERROR reading array COORDS" << endl;
439 }
440
441 // Copy unique node x,y,z coordinates into separate arrays,
442 // which will be passed to silo writer:
443 uint64_t counter = 0;
444 Real* xcrds = new Real[nodes.size()];
445 Real* ycrds = new Real[nodes.size()];
446 Real* zcrds = new Real[nodes.size()];
447 for (map<NodeCrd<Real>,uint64_t>::iterator it=nodes.begin(); it!=nodes.end(); ++it) {
448 it->second = counter;
449 xcrds[counter] = it->first.x;
450 ycrds[counter] = it->first.y;
451 zcrds[counter] = it->first.z;
452 ++counter;
453 }
454
455 // Read through the coordinate array again and create a node list. Each 3D spatial cell is
456 // associated with 8 nodes, and most of these nodes are shared with neighbouring cells. In
457 // order to get VisIt display the data correctly, the duplicate nodes should not be used.
458 // Here we create a list of indices into xcrds,ycrds,zcrds arrays, with eight entries per cell:
459 int* nodelist = new int[8*cellIds.size()];
460 i = 0;
461 for( vector<uint64_t>::const_iterator it = cellIds.begin(); it != cellIds.end(); ++it, ++i ) {
462 // Read the bottom lower left corner coordinates of a cell and its sizes. Note
463 // that zones will end up in SILO file in the same order as they are in VLSV file.
464
465 //Get cell coordinates:
466 const uint64_t cellId = *it;
467 array<Real, 3> coordinates;
468 //Store the coordinates in 'coordinates' std::array
469 getCellCoordinates( cellStruct, cellId, coordinates );
470
471 //Note: cellStruct.cell_length[i] = a cell's length in i direction
472 Real X0 = coordinates[0];
473 Real X1 = coordinates[0]+cellStruct.cell_length[0];
474 Real Y0 = coordinates[1];
475 Real Y1 = coordinates[1]+cellStruct.cell_length[1];
476 Real Z0 = coordinates[2];
477 Real Z1 = coordinates[2]+cellStruct.cell_length[2];
478
479 // Flush very small coordinate values to zero:
480 if (fabs(X0) < EPS) X0 = 0.0;
481 if (fabs(X1) < EPS) X1 = 0.0;
482 if (fabs(Y0) < EPS) Y0 = 0.0;
483 if (fabs(Y1) < EPS) Y1 = 0.0;
484 if (fabs(Z0) < EPS) Z0 = 0.0;
485 if (fabs(Z1) < EPS) Z1 = 0.0;
486
487 // Search the cell's nodes from the map created above. For each node in nodelist
488 // store an index into an array which only contains the unique nodes:
489 map<NodeCrd<Real>,uint64_t,NodeComp>::const_iterator it2;
490 it2 = nodes.find(NodeCrd<Real>(X0,Y0,Z0)); if (it2 == nodes.end()) success = false; nodelist[i*8+0] = it2->second;
491 it2 = nodes.find(NodeCrd<Real>(X1,Y0,Z0)); if (it2 == nodes.end()) success = false; nodelist[i*8+1] = it2->second;
492 it2 = nodes.find(NodeCrd<Real>(X1,Y1,Z0)); if (it2 == nodes.end()) success = false; nodelist[i*8+2] = it2->second;
493 it2 = nodes.find(NodeCrd<Real>(X0,Y1,Z0)); if (it2 == nodes.end()) success = false; nodelist[i*8+3] = it2->second;
494 it2 = nodes.find(NodeCrd<Real>(X0,Y0,Z1)); if (it2 == nodes.end()) success = false; nodelist[i*8+4] = it2->second;
495 it2 = nodes.find(NodeCrd<Real>(X1,Y0,Z1)); if (it2 == nodes.end()) success = false; nodelist[i*8+5] = it2->second;
496 it2 = nodes.find(NodeCrd<Real>(X1,Y1,Z1)); if (it2 == nodes.end()) success = false; nodelist[i*8+6] = it2->second;
497 it2 = nodes.find(NodeCrd<Real>(X0,Y1,Z1)); if (it2 == nodes.end()) success = false; nodelist[i*8+7] = it2->second;
498 }
499 //O: REMOVE THIS
500 //delete coordsBuffer;
501 if (success == false) {
502 cerr << "Failed to find node(s)" << endl;
503 }
504
505 // Write the unstructured mesh to SILO file:
506 const int N_dims = 3; // Number of dimensions
507 const int N_nodes = nodes.size(); // Total number of nodes
508 const int N_zones = cellIds.size(); // Total number of zones (=spatial cells)
509 int shapeTypes[] = {DB_ZONETYPE_HEX}; // Hexahedrons only
510 int shapeSizes[] = {8}; // Each hexahedron has 8 nodes
511 int shapeCnt[] = {N_zones}; // Only 1 shape type (hexahedron)
512 const int N_shapes = 1; // -- "" --
513
514 void* coords[3]; // Pointers to coordinate arrays
515 coords[0] = xcrds;
516 coords[1] = ycrds;
517 coords[2] = zcrds;
518
519 // Write zone list into silo file:
520 const string zoneListName = meshName + "Zones";
521 if (DBPutZonelist2(fileptr,zoneListName.c_str(),N_zones,N_dims,nodelist,8*cellIds.size(),0,0,0,shapeTypes,shapeSizes,shapeCnt,N_shapes,NULL) < 0) success = false;
522
523 // Write grid into silo file:
524 if (DBPutUcdmesh(fileptr,meshName.c_str(),N_dims,NULL,coords,N_nodes,N_zones,zoneListName.c_str(),NULL,SiloType(datatype::type::FLOAT,sizeof(Real)),NULL) < 0) success = false;
525
526 nodes.clear();
527 delete nodelist;
528 delete xcrds;
529 delete ycrds;
530 delete zcrds;
531
532 // Write the cell IDs as a variable:
533 string cellIDlabel = "Cell ID";
534 DBoptlist* optList = DBMakeOptlist(1);
535 DBAddOption(optList,DBOPT_LABEL,const_cast<char*>(cellIDlabel.c_str()));
536 //Note: cellIds is of type uint
537 if (DBPutUcdvar1(fileptr,"CellID",meshName.c_str(),reinterpret_cast<char*>(cellIds.data()),cellIds.size(),NULL,0,SiloType(datatype::type::UINT,sizeof(uint64_t)),DB_ZONECENT,NULL) < 0) success = false;
538// delete buffer;
539 DBFreeOptlist(optList);
540
541 // Write all variables of this mesh into silo file:
542 list<string> variables;
543 vlsvReader.getVariableNames(meshName,variables);
544 for (list<string>::const_iterator it=variables.begin(); it!=variables.end(); ++it) {
545 if (convertMeshVariable(vlsvReader,meshName,*it) == false) success = false;
546 }
547 return success;
548
549}
550
551
552template <class T>
553bool convertSILO(const string& fname) {
554 bool success = true;
555
556
557 // Open VLSV file for reading:
558 T vlsvReader;
559 if (vlsvReader.open(fname) == false) {
560 cerr << "Failed to open '" << fname << "'" << endl;
561 return false;
562 }
563
564
565 // Open SILO file for writing:
566 size_t found=fname.find_last_of("/\\");
567 //remove path from vlsvfile name
568 string fileout = fname.substr(found+1);
569 size_t pos = fileout.rfind(".vlsv");
570 if (pos != string::npos) fileout.replace(pos,5,".silo");
571
572 fileptr = DBCreate(fileout.c_str(),DB_CLOBBER,DB_LOCAL,"Vlasov data file",DB_PDB);
573 if (fileptr == NULL) return false;
574
575 // Get the names of all meshes in vlsv file, and write into silo file:
576 list<string> meshNames;
577 if (vlsvReader.getMeshNames(meshNames) == false) {
578 DBClose(fileptr);
579 return false;
580 }
581 for (list<string>::const_iterator it=meshNames.begin(); it!=meshNames.end(); ++it) {
582 if (convertMesh(vlsvReader,*it) == false) {
583 DBClose(fileptr);
584 return false;
585 }
586 }
587 vlsvReader.close();
588 DBClose(fileptr);
589 return success;
590}
591
592int main(int argn,char* args[]) {
593 int ntasks, rank;
594 MPI_Init(&argn, &args);
595 MPI_Comm_size(MPI_COMM_WORLD, &ntasks);
596 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
597
598 if (rank == 0 && argn < 2) {
599 cout << endl;
600 cout << "USAGE: ./vlsv2vtk <input file mask(s)>" << endl;
601 cout << "Each VLSV in the current directory is compared against the given file mask(s)," << endl;
602 cout << "and if match is found, that file is converted into SILO format." << endl;
603 cout << endl;
604 return 1;
605 }
606
607 // Convert file masks into strings:
608 vector<string> masks, fileList;
609 for (int i=1; i<argn; ++i) masks.push_back(args[i]);
610
611 // Compare directory contents against each mask:
612
613 const string suffix = ".vlsv";
614 int filesFound = 0, filesConverted = 0;
615 for (size_t mask=0; mask<masks.size(); ++mask) {
616 size_t found=masks[mask].find_last_of("/\\");
617 string directory=".";
618 if(found != string::npos)
619 directory = masks[mask].substr(0,found);
620 const string maskName = masks[mask].substr(found+1);
621
622 if(rank == 0) {cout << "Comparing mask '" << maskName << "' in folder '" << directory <<"'" << endl;}
623 DIR* dir = opendir(directory.c_str());
624 if (dir == NULL) continue;
625
626 struct dirent* entry = readdir(dir);
627 while (entry != NULL) {
628 const string entryName = entry->d_name;
629 // Compare entry name against given mask and file suffix ".vlsv":
630 if (entryName.find(maskName) == string::npos || entryName.find(suffix) == string::npos) {
631 entry = readdir(dir);
632 continue;
633 }
634
635 fileList.push_back(directory);
636 fileList.back().append("/");
637 fileList.back().append(entryName);
638 filesFound++;
639 entry = readdir(dir);
640 }
641 closedir(dir);
642 if (rank == 0 && filesFound == 0) cout << "\t no matches found" << endl;
643 }
644
645 for(size_t entryName = 0; entryName < fileList.size(); entryName++) {
646 if(entryName%ntasks == (uint)rank) {
647 cout << "\tProc " << rank << " converting '" << fileList[entryName] << "'" << endl;
648 convertSILO<vlsvinterface::Reader>(fileList[entryName]);
649 filesConverted++;
650 }
651 }
652
653 int totalFilesConverted =0;
654 MPI_Reduce(&filesConverted, &totalFilesConverted, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
655 if (rank == 0 && totalFilesConverted == 0) cout << "\t no files converted" << endl;
656
657 MPI_Finalize();
658 return 0;
659}
for i
Definition Dispersion.m:24
bool getVariableNames(const std::string &, std::list< std::string > &meshNames)
bool getCellIds(std::vector< uint64_t > &cellIds, const std::string &meshName="SpatialGrid")
float Real
Definition definitions.h:41
static creal EPS
Definition fs_common.h:61
const int j
const int k
const Realf vz_min
uint64_t vcell_bounds[3]
Definition vlsv2silo.cpp:52
Real min_vcoordinates[3]
Definition vlsv2silo.cpp:56
Real vblock_length[3]
Definition vlsv2silo.cpp:54
uint64_t cell_bounds[3]
Definition vlsv2silo.cpp:45
Real min_coordinates[3]
Definition vlsv2silo.cpp:49
Real cell_length[3]
Definition vlsv2silo.cpp:47
bool operator()(const NodeCrd< double > &a, const NodeCrd< double > &b) const
bool operator()(const NodeCrd< float > &a, const NodeCrd< float > &b) const
NodeCrd(const REAL &x, const REAL &y, const REAL &z)
bool comp(const NodeCrd< REAL > &n) const
static REAL EPS
int main()
static ARCH_HOSTDEV VecSimple< T > max(VecSimple< T > const &l, VecSimple< T > const &r)
uint64_t convUInt(const char *ptr, const T &dataType, const uint64_t &dataSize)
int SiloType(const datatype::type &dataType, const uint64_t &dataSize)
bool convertSILO(const string &fname)
void setCellVariables(vlsvinterface::Reader &vlsvReader, CellStructure &cellStruct)
Definition vlsv2silo.cpp:93
bool convertMeshVariable(T &vlsvReader, const string &meshName, const string &varName)
bool isDataTypeUint(vlsv::datatype::type &dataType)
static DBfile * fileptr
bool convertMesh(vlsvinterface::Reader &vlsvReader, const string &meshName)
void getCellCoordinates(const CellStructure &cellStruct, const uint64_t _cellId, array< Real, 3 > &coordinates)
Definition vlsv2silo.cpp:68