Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
vlsvextract.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 <iostream>
24
25#include <limits>
26#include <stdint.h>
27#include <cmath>
28#include <list>
29#include <sstream>
30#include <dirent.h>
31#include <stdio.h>
32
33#include <unordered_set>
34
35#include <vlsv_reader.h>
36#include <vlsv_writer.h>
37#include <vlsv_amr.h>
38#include <boost/program_options.hpp>
39#include <Eigen/Dense>
40#include <phiprof.hpp>
41
42#include "vlsv_util.h"
43#include "vlsvreaderinterface.h"
44#include "vlsvextract.h"
45
46using namespace std;
47using namespace Eigen;
48using namespace vlsv;
49namespace po = boost::program_options;
50
51// If set to true, vlsvextract writes some debugging info to stderr
52static bool runDebug = false;
53
54bool NodeComp::operator()(const NodeCrd<double>& a, const NodeCrd<double>& b) const {
55 double EPS = 0.5e-3 * (fabs(a.z) + fabs(b.z));
56 if (a.z > b.z + EPS) return false;
57 if (a.z < b.z - EPS) return true;
58
59 EPS = 0.5e-3 * (fabs(a.y) + fabs(b.y));
60 if (a.y > b.y + EPS) return false;
61 if (a.y < b.y - EPS) return true;
62
63 EPS = 0.5e-3 * (fabs(a.x) + fabs(b.x));
64 if (a.x > b.x + EPS) return false;
65 if (a.x < b.x - EPS) return true;
66 return false;
67}
68
69bool NodeComp::operator()(const NodeCrd<float>& a,const NodeCrd<float>& b) const {
70 float EPS = 0.5e-3 * (fabs(a.z) + fabs(b.z));
71 if (a.z > b.z + EPS) return false;
72 if (a.z < b.z - EPS) return true;
73
74 EPS = 0.5e-3 * (fabs(a.y) + fabs(b.y));
75 if (a.y > b.y + EPS) return false;
76 if (a.y < b.y - EPS) return true;
77
78 EPS = 0.5e-3 * (fabs(a.x) + fabs(b.x));
79 if (a.x > b.x + EPS) return false;
80 if (a.x < b.x - EPS) return true;
81 return false;
82}
83
84uint64_t convUInt(const char* ptr, const datatype::type & dataType, const uint64_t& dataSize) {
85 if (dataType != datatype::type::UINT) {
86 cerr << "Erroneous datatype given to convUInt" << endl;
87 exit(1);
88 }
89
90 switch (dataSize) {
91 case 1:
92 return *reinterpret_cast<const unsigned char*> (ptr);
93 break;
94 case 2:
95 return *reinterpret_cast<const unsigned short int*> (ptr);
96 break;
97 case 4:
98 return *reinterpret_cast<const unsigned int*> (ptr);
99 break;
100 case 8:
101 return *reinterpret_cast<const unsigned long int*> (ptr);
102 break;
103 }
104 return 0;
105}
106
107bool convertSlicedVelocityMesh(vlsvinterface::Reader& vlsvReader,const string& fname,const string& meshName,
108 CellStructure& cellStruct,const std::string& popName) {
109 bool success = true;
110
111 // TEST
112 cellStruct.slicedCoords[0] = 2;
113 cellStruct.slicedCoords[1] = 4;
114 cellStruct.slicedCoords[2] = 5;
115 cellStruct.slicedCoordValues[0] = 1e3;
116 cellStruct.slicedCoordValues[1] = -5e3;
117 cellStruct.slicedCoordValues[2] = 5e3;
118
119 string outputMeshName = "VelSlice";
120 vlsv::Writer out;
121 if (out.open(fname,MPI_COMM_SELF,0) == false) {
122 cerr << "ERROR, failed to open output file with vlsv::Writer at " << __FILE__ << " " << __LINE__ << endl;
123 return false;
124 }
125
126 std::vector<uint64_t> cellIDs;
127 if (vlsvReader.getCellIds(cellIDs) == false) {
128 cerr << "ERROR: failed to get cell IDs in " << __FILE__ << ' ' << __LINE__ << endl;
129 return false;
130 }
131
132 uint64_t bbox[6]; // Number of cells in the generated mesh
133 int dims[3]; // Output dimensions
134 if (cellStruct.slicedCoords[0] == 0) {
135 dims[0] = 1; dims[1] = 2;
136 bbox[0] = cellStruct.cell_bounds[1]; bbox[1] = cellStruct.cell_bounds[2];
137 } else if (cellStruct.slicedCoords[0] == 1) {
138 dims[0] = 0; dims[1] = 2;
139 bbox[0] = cellStruct.cell_bounds[0]; bbox[1] = cellStruct.cell_bounds[2];
140 } else {
141 dims[0] = 0; dims[1] = 1;
142 bbox[0] = cellStruct.cell_bounds[0]; bbox[1] = cellStruct.cell_bounds[2];
143 }
144 bbox[3]=1; bbox[4]=1; bbox[5]=4;
145
146 dims[2]=3;
147 if (cellStruct.slicedCoords[1] == 3) dims[2] = 4;
148 if (cellStruct.slicedCoords[2] == 4) dims[2] = 5;
149
150 if (vlsv::initMesh(cellStruct.vcell_bounds[0],cellStruct.vcell_bounds[0],cellStruct.vcell_bounds[0],cellStruct.maxVelRefLevel) == false) {
151 cerr << "ERROR: failed to init AMR mesh in " << __FILE__ << ' ' << __LINE__ << endl;
152 return false;
153 }
154
155 // Get the names of velocity mesh variables
156 set<string> blockVarNames;
157 const string attributeName = "name";
158 if (vlsvReader.getUniqueAttributeValues("BLOCKVARIABLE",attributeName,blockVarNames) == false) {
159 cerr << "ERROR, FAILED TO GET UNIQUE ATTRIBUTE VALUES AT " << __FILE__ << " " << __LINE__ << endl;
160 }
161
162 struct BlockVarInfo {
163 string name;
164 vlsv::datatype::type dataType;
165 uint64_t vectorSize;
166 uint64_t dataSize;
167 };
168 std::vector<BlockVarInfo> varInfo;
169
170 // Assume that two of the coordinates are spatial, i.e., that the first
171 // sliced coordinate is a spatial one
172 std::vector<float> nodeCoords;
173 std::vector<int> connectivity;
174 std::vector<std::vector<char> > variables;
175 for (size_t cell=0; cell<cellIDs.size(); ++cell) {
176 uint64_t cellId = cellIDs[cell]-1;
177 uint64_t cellIndices[3];
178 cellIndices[0] = cellId % cellStruct.cell_bounds[0];
179 cellIndices[1] = ((cellId - cellIndices[0]) / cellStruct.cell_bounds[0]) % cellStruct.cell_bounds[1];
180 cellIndices[2] = ((cellId - cellStruct.cell_bounds[0]*cellIndices[1]) / (cellStruct.cell_bounds[0]*cellStruct.cell_bounds[1]));
181
182 // Calculate cell coordinates and check if the sliced spatial coordinate is in it
183 Real cellCrds[6];
184 for (int i=0; i<3; ++i) cellCrds[i ] = cellStruct.min_coordinates[i] + cellIndices[i] * cellStruct.cell_length[i];
185 for (int i=0; i<3; ++i) cellCrds[i+3] = cellStruct.min_coordinates[i] + (cellIndices[i]+1)* cellStruct.cell_length[i];
186
187 if (cellCrds[cellStruct.slicedCoords[0]] > cellStruct.slicedCoordValues[0]) continue;
188 if (cellCrds[cellStruct.slicedCoords[0]+3] < cellStruct.slicedCoordValues[0]) continue;
189
190 // Buffer all velocity mesh variables
191 std::vector<char*> varBuffer(blockVarNames.size());
192 int counter=0;
193 for (set<string>::const_iterator var=blockVarNames.begin(); var!=blockVarNames.end(); ++var) {
194 varBuffer[counter] = NULL;
195 if (vlsvReader.getVelocityBlockVariables(*var,cellIDs[cell],varBuffer[counter],true) == false) {
196 varBuffer[counter] = NULL;
197 }
198 ++counter;
199 }
200
201 // Store block variable info, we need this to write the variable data
202 varInfo.clear();
203 for (set<string>::const_iterator var=blockVarNames.begin(); var!=blockVarNames.end(); ++var) {
204 list<pair<string,string> > attribs;
205 attribs.push_back(make_pair("name",*var));
206 attribs.push_back(make_pair("mesh",meshName));
207 uint64_t arraySize;
208 BlockVarInfo vinfo;
209 vinfo.name = *var;
210 if (vlsvReader.getArrayInfo("BLOCKVARIABLE",attribs,arraySize,vinfo.vectorSize,vinfo.dataType,vinfo.dataSize) == false) {
211 cerr << "Could not read BLOCKVARIABLE array info" << endl;
212 }
213 varInfo.push_back(vinfo);
214 }
215 if (varInfo.size() > variables.size()) variables.resize(varInfo.size());
216
217 std::vector<uint64_t> blockIDs;
218 if (vlsvReader.getBlockIds(cellIDs[cell],blockIDs,popName) == false) {
219 for (size_t v=0; v<varBuffer.size(); ++v) delete [] varBuffer[v];
220 continue;
221 }
222
223 counter=0;
224 for (size_t b=0; b<blockIDs.size(); ++b) {
225 uint64_t blockGID = blockIDs[b];
226
227 // Figure out block indices and refinement level
228 uint32_t refLevel;
229 uint32_t blockIndices[3];
230 vlsv::calculateCellIndices(blockGID,refLevel,blockIndices[0],blockIndices[1],blockIndices[2]);
231 uint32_t refMul = pow(2,refLevel);
232 uint32_t refDiff = pow(2,cellStruct.maxVelRefLevel-refLevel);
233
234 // Calculate block coordinates
235 Real minBlockCoords[3];
236 Real maxBlockCoords[3];
237 for (int i=0; i<3; ++i) {
238 minBlockCoords[i] = cellStruct.min_vcoordinates[i] + blockIndices[i]*cellStruct.vblock_length[i]/refMul;
239 maxBlockCoords[i] = cellStruct.min_vcoordinates[i] + (blockIndices[i]+1)*cellStruct.vblock_length[i]/refMul;
240 }
241
242 // If the chosen velocity coordinates are in the block, store
243 // the relevant cell (with correct size in velocity direction)
244 if (cellStruct.slicedCoordValues[1] < minBlockCoords[cellStruct.slicedCoords[1]-3]
245 || cellStruct.slicedCoordValues[1] > maxBlockCoords[cellStruct.slicedCoords[1]-3]) continue;
246 if (cellStruct.slicedCoordValues[2] < minBlockCoords[cellStruct.slicedCoords[2]-3]
247 || cellStruct.slicedCoordValues[2] > maxBlockCoords[cellStruct.slicedCoords[2]-3]) continue;
248
249 // Store node coordinates and cell connectivity entries for the accepted cells
250 const Real DV_cell = cellStruct.vblock_length[dims[2]-3]/refMul/4;
251 for (int i=0; i<4; ++i) {
252 const size_t offset = nodeCoords.size()/3;
253 nodeCoords.push_back(cellCrds[dims[0] ]); nodeCoords.push_back(cellCrds[dims[1] ]); nodeCoords.push_back(minBlockCoords[dims[2]-3]+i*DV_cell);
254 nodeCoords.push_back(cellCrds[dims[0]+3]); nodeCoords.push_back(cellCrds[dims[1] ]); nodeCoords.push_back(minBlockCoords[dims[2]-3]+i*DV_cell);
255 nodeCoords.push_back(cellCrds[dims[0] ]); nodeCoords.push_back(cellCrds[dims[1]+3]); nodeCoords.push_back(minBlockCoords[dims[2]-3]+i*DV_cell);
256 nodeCoords.push_back(cellCrds[dims[0]+3]); nodeCoords.push_back(cellCrds[dims[1]+3]); nodeCoords.push_back(minBlockCoords[dims[2]-3]+i*DV_cell);
257 nodeCoords.push_back(cellCrds[dims[0] ]); nodeCoords.push_back(cellCrds[dims[1] ]); nodeCoords.push_back(minBlockCoords[dims[2]-3]+(i+1)*DV_cell);
258 nodeCoords.push_back(cellCrds[dims[0]+3]); nodeCoords.push_back(cellCrds[dims[1] ]); nodeCoords.push_back(minBlockCoords[dims[2]-3]+(i+1)*DV_cell);
259 nodeCoords.push_back(cellCrds[dims[0] ]); nodeCoords.push_back(cellCrds[dims[1]+3]); nodeCoords.push_back(minBlockCoords[dims[2]-3]+(i+1)*DV_cell);
260 nodeCoords.push_back(cellCrds[dims[0]+3]); nodeCoords.push_back(cellCrds[dims[1]+3]); nodeCoords.push_back(minBlockCoords[dims[2]-3]+(i+1)*DV_cell);
261
262 connectivity.push_back(vlsv::celltype::VOXEL);
263 connectivity.push_back(8);
264 for (int j=0; j<8; ++j) connectivity.push_back(offset+j);
265 }
266
267 // Store value of distribution function in saved cells
268 const Real DVY_CELL = cellStruct.vblock_length[cellStruct.slicedCoords[1]-3]/refMul;
269 const Real DVZ_CELL = cellStruct.vblock_length[cellStruct.slicedCoords[2]-3]/refMul;
270 int j = static_cast<int>((cellStruct.slicedCoordValues[1] - minBlockCoords[cellStruct.slicedCoords[1]-3]) / DVY_CELL);
271 int k = static_cast<int>((cellStruct.slicedCoordValues[2] - minBlockCoords[cellStruct.slicedCoords[2]-3]) / DVY_CELL);
272
273 for (size_t v=0; v<varBuffer.size(); ++v) {
274 uint64_t entrySize = varInfo[v].vectorSize*varInfo[v].dataSize;
275 char* baseptr = &(varBuffer[v][0]) + b*entrySize;
276
277 for (int i=0; i<4; ++i) {
278 char* varptr = baseptr + i*varInfo[v].dataSize;
279 int index;
280 switch (dims[2]) {
281 case 3:
282 for (uint64_t dummy=0; dummy<varInfo[v].dataSize; ++dummy) variables[v].push_back(varptr[dummy]);
283 break;
284 case 4:
285 for (uint64_t dummy=0; dummy<varInfo[v].dataSize; ++dummy) variables[v].push_back(varptr[dummy]);
286 break;
287 case 5:
288 for (uint64_t dummy=0; dummy<varInfo[v].dataSize; ++dummy) variables[v].push_back(varptr[dummy]);
289 break;
290 }
291 }
292 }
293 ++counter;
294 }
295
296 for (size_t v=0; v<varBuffer.size(); ++v) delete [] varBuffer[v];
297 }
298
299 map<string,string> attributes;
300 attributes["name"] = outputMeshName;
301 attributes["type"] = vlsv::mesh::STRING_UCD_GENERIC_MULTI;
302 attributes["domains"] = "1";
303 attributes["cells"] = connectivity.size()/10;
304 attributes["nodes"] = nodeCoords.size()/3;
305
306 if (out.writeArray("MESH",attributes,connectivity.size(),1,&(connectivity[0])) == false) success = false;
307
308 attributes.clear();
309 attributes["mesh"] = outputMeshName;
310 if (out.writeArray("MESH_NODE_CRDS",attributes,nodeCoords.size()/3,3,&(nodeCoords[0])) == false) success = false;
311
312 bbox[0]=1; bbox[1]=1; bbox[2]=1; bbox[3]=1; bbox[4]=1; bbox[5]=1;
313 if (out.writeArray("MESH_BBOX",attributes,6,1,bbox) == false) success = false;
314
315 uint32_t offsetEntries[vlsv::ucdgenericmulti::offsets::SIZE];
316 offsetEntries[vlsv::ucdgenericmulti::offsets::ZONE_ENTRIES] = connectivity.size();
317 offsetEntries[vlsv::ucdgenericmulti::offsets::NODE_ENTRIES] = nodeCoords.size()/3;
318 if (out.writeArray("MESH_OFFSETS",attributes,1,vlsv::ucdgenericmulti::offsets::SIZE,offsetEntries) == false) success=false;
319
320 uint32_t domainSize[vlsv::ucdgenericmulti::domainsizes::SIZE];
321 domainSize[vlsv::ucdgenericmulti::domainsizes::TOTAL_BLOCKS] = connectivity.size()/10;
322 domainSize[vlsv::ucdgenericmulti::domainsizes::GHOST_BLOCKS] = 0;
323 domainSize[vlsv::ucdgenericmulti::domainsizes::TOTAL_NODES] = nodeCoords.size()/3;
324 domainSize[vlsv::ucdgenericmulti::domainsizes::GHOST_NODES] = 0;
325 if (out.writeArray("MESH_DOMAIN_SIZES",attributes,1,vlsv::ucdgenericmulti::domainsizes::SIZE,domainSize) == false) success = false;
326
327 for (size_t v=0; v<variables.size(); ++v) {
328 uint64_t vectorSize = varInfo[v].vectorSize/64;
329 uint64_t entrySize = vectorSize*varInfo[v].dataSize;
330 uint64_t arraySize = variables[v].size() / entrySize;
331 if (variables[v].size() % entrySize != 0) {
332 cerr << "Error in variable array size in " << __FILE__ << ' ' << __LINE__ << endl;
333 continue;
334 }
335
336 attributes["name"] = varInfo[v].name;
337 char* ptr = reinterpret_cast<char*>(&(variables[v][0]));
338 if (out.writeArray("VARIABLE",attributes,vlsv::getStringDatatype(varInfo[v].dataType),arraySize,vectorSize,varInfo[v].dataSize,ptr) == false) {
339 cerr << "Failed to write variable '" << varInfo[v].name << "' to sliced velocity mesh" << endl;
340 }
341 }
342
343 out.close();
344 return success;
345}
346
347void applyTranslation(const Real* V_bulk,Real* transform) {
348 // Translation matrix, defaults to identity matrix
349 Real mat[16];
350 for (int i=0; i<16; ++i) mat[i] = 0;
351 mat[0 ] = 1;
352 mat[5 ] = 1;
353 mat[10] = 1;
354 mat[15] = 1;
355 mat[3 ] = -V_bulk[0];
356 mat[7 ] = -V_bulk[1];
357 mat[11] = -V_bulk[2];
358
359 // Copy of transformation matrix
360 Real T[16];
361 for (int i=0; i<16; ++i) T[i] = transform[i];
362
363 // Apply translation to transformation matrix:
364 for (int k=0; k<4; ++k) {
365 for (int i=0; i<4; ++i) {
366 transform[k*4+i] = 0;
367 for (int j=0; j<4; ++j) transform[k*4+i] += mat[k*4+j]*T[j*4+i];
368 }
369 }
370}
371
372void applyRotation(const Real* B,Real* transform) {
373 // Now we have the B vector, so now the idea is to rotate the v-coordinates so that B always faces z-direction
374 // Since we're handling only one spatial cell, B is the same in every v-coordinate.
375 const int _size = 3;
376
377 Real rotAngle = 0.0;
378 Matrix<Real, _size, 1> _B(B[0], B[1], B[2]);
379 Matrix<Real, _size, 1> unit_z(0, 0, 1); // Unit vector in z-direction
380 Matrix<Real, _size, 1> Bxu = _B.cross( unit_z ); // Cross product of B and unit_z
381
382 // Check if divide by zero -- if there's division by zero, the B vector
383 // is already in the direction of z-axis and no need to do anything
384 if ( (Bxu[0]*Bxu[0] + Bxu[1]*Bxu[1] + Bxu[2]*Bxu[2]) != 0 ) {
385 // Determine the axis of rotation: (Note: Bxu[2] is zero)
386 Matrix<Real, _size, 1> axisDir = Bxu/(sqrt(Bxu[0]*Bxu[0] + Bxu[1]*Bxu[1] + Bxu[2]*Bxu[2]));
387
388 // Determine the angle of rotation: (No need for a check for div/by/zero because of the above check)
389 rotAngle = -1 * acos(_B[2] / sqrt(_B[0]*_B[0] + _B[1]*_B[1] + _B[2]*_B[2])); //B_z / |B|
390
391 // Determine the rotation matrix and copy to output
392 Transform<Real, _size, _size> rotationMatrix( AngleAxis<Real>(rotAngle, axisDir) );
393
394 // Rotation matrix
395 double Rot[16];
396 for (int i=0; i<16; ++i) Rot[i] = 0;
397 Rot[0 ] = 1;
398 Rot[5 ] = 1;
399 Rot[10] = 1;
400 Rot[15] = 1;
401 for (int j=0; j<3; ++j) for (int i=0; i<3; ++i) Rot[j*4+i] = rotationMatrix(i,j);
402
403 // Copy of transformation matrix
404 double T[16];
405 for (int i=0; i<16; ++i) T[i] = transform[i];
406
407 // Apply rotation to transformation matrix
408 for (int k=0; k<4; ++k) {
409 for (int i=0; i<4; ++i) {
410 transform[k*4+i] = 0;
411 for (int j=0; j<4; ++j) {
412 transform[k*4+i] += Rot[k*4+j]*T[j*4+i];
413 }
414 }
415 }
416 }
417
418 if (runDebug == true) {
419 cerr << "***** DEBUGGING INFO FOR applyRotation() *****" << endl;
420 cerr << "B = " << B[0] << '\t' << B[1] << '\t' << B[2] << endl;
421 cerr << "rotAngle is " << 180.0/M_PI*rotAngle << " degrees " << endl;
422 cerr << endl;
423 cerr << "transform matrix components:" << endl;
424 for (int k=0; k<4; ++k) {
425 cerr << '\t';
426 for (int i=0; i<4; ++i) {
427 cerr << transform[k*4+i] << '\t';
428 }
429 cerr << endl;
430 }
431 cerr << endl;
432
433 Real B_rot[3];
434 B_rot[0] = transform[0]*B[0] + transform[1]*B[1] + transform[2 ]*B[2];
435 B_rot[1] = transform[4]*B[0] + transform[5]*B[1] + transform[6 ]*B[2];
436 B_rot[2] = transform[8]*B[0] + transform[9]*B[1] + transform[10]*B[2];
437 Real B_mag = sqrt(B[0]*B[0] + B[1]*B[1] + B[2]*B[2]);
438 Real B_rot_mag = sqrt(B_rot[0]*B_rot[0] + B_rot[1]*B_rot[1] + B_rot[2]*B_rot[2]);
439
440 cerr << "magnitude B = " << B_mag << endl;
441 cerr << "magnitude B (rotated) = " << B_rot_mag << endl;
442 cerr << "abs difference = " << fabs(B_mag-B_rot_mag) << endl;
443 cerr << endl;
444
445 cerr << "Rotated B direction = " << B_rot[0]/B_rot_mag << '\t' << B_rot[1]/B_rot_mag << '\t' << B_rot[2]/B_rot_mag << endl;
446 cerr << endl;
447 }
448}
449
450void getBulkVelocity(Real* V_bulk,vlsvinterface::Reader& vlsvReader,const string& meshName,const string& popName,const uint64_t& cellID) {
451 //Declarations
452 vlsv::datatype::type cellIdDataType;
453 uint64_t cellIdArraySize, cellIdVectorSize, cellIdDataSize;
454
455 list<pair<string,string> > xmlAttributes;
456 xmlAttributes.push_back(make_pair("mesh",meshName));
457 xmlAttributes.push_back(make_pair("name","CellID"));
458 if (vlsvReader.getArrayInfo("VARIABLE", xmlAttributes, cellIdArraySize, cellIdVectorSize, cellIdDataType, cellIdDataSize) == false) {
459 cerr << "Error " << __FILE__ << " " << __LINE__ << endl;
460 exit(1);
461 }
462
463 // Declare buffers and allocate memory, this is done to read in the cell id location:
464 uint64_t* cellIdBuffer = NULL;
465
466 // Read the array into cellIdBuffer starting from 0 up until cellIdArraySize
467 // which was received from getArrayInfo
468 if (vlsvReader.read("VARIABLE",xmlAttributes,0,cellIdArraySize,cellIdBuffer,true) == false) {
469 cerr << "Error: failed to read cell IDs in " << __FILE__ << ":" << __LINE__ << endl;
470 delete [] cellIdBuffer;
471 exit(1);
472 }
473
474 // Search for the given cellID location, the array in the vlsv file is not ordered depending
475 // on the cell id so the array might look like this,
476 // for instance: [CellId1, CellId7, CellId5, ...] and the variables are saved in the same
477 // order: [CellId1_B_FIELD, CellId7_B_FIELD, CellId5_B_FIELD, ...]
478 uint64_t cellIndex = numeric_limits<uint64_t>::max();
479 for (uint64_t cell=0; cell<cellIdArraySize; ++cell) {
480 // the CellID are not sorted in the array, so we'll have to search
481 // the array -- the CellID is stored in cellId
482 if (cellID == cellIdBuffer[cell]) {
483 //Found the right cell ID, break
484 cellIndex = cell; break;
485 }
486 }
487 delete [] cellIdBuffer; cellIdBuffer = NULL;
488
489 // Check if the cell id was found:
490 if (cellIndex == numeric_limits<uint64_t>::max()) {
491 cerr << "Spatial cell #" << cellID << " not found in " << __FILE__ << ":" << __LINE__ << endl;
492 exit(1);
493 }
494
495 do {
496 // Read combined vg_v
497 double velocity[3];
498 double* ptr = velocity;
499 xmlAttributes.clear();
500 xmlAttributes.push_back(make_pair("mesh",meshName));
501 xmlAttributes.push_back(make_pair("name","vg_v"));
502 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,ptr,false) == true) {
503 cerr << "NOTE: Using combined vg_v (all populations!) for plasma frame shifting." << endl;
504 V_bulk[0] = velocity[0];
505 V_bulk[0] = velocity[0];
506 V_bulk[0] = velocity[0];
507 break;
508 }
509 // Read <pop>/vg_v
510 xmlAttributes.clear();
511 xmlAttributes.push_back(make_pair("mesh",meshName));
512 xmlAttributes.push_back(make_pair("name",popName+"/vg_v"));
513 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,ptr,false) == true) {
514 cerr << "NOTE: Using <pop>/vg_v for plasma frame shifting." << endl;
515 V_bulk[0] = velocity[0];
516 V_bulk[0] = velocity[0];
517 V_bulk[0] = velocity[0];
518 break;
519 }
520 // Try old style
521 // Read number density
522 double numberDensity;
523 ptr = &numberDensity;
524 xmlAttributes.clear();
525 xmlAttributes.push_back(make_pair("mesh",meshName));
526 xmlAttributes.push_back(make_pair("name","rho"));
527 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,ptr,false) == true) {
528 // Read number density times velocity
529 double momentum[3];
530 ptr = momentum;
531 xmlAttributes.clear();
532 xmlAttributes.push_back(make_pair("mesh",meshName));
533 xmlAttributes.push_back(make_pair("name","rho_v"));
534 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,ptr,false) == true) {
535 cerr << "NOTE: Using rho_v / rho for plasma frame shifting." << endl;
536 V_bulk[0] = momentum[0] / (numberDensity + numeric_limits<double>::min());
537 V_bulk[1] = momentum[1] / (numberDensity + numeric_limits<double>::min());
538 V_bulk[2] = momentum[2] / (numberDensity + numeric_limits<double>::min());
539 break;
540 }
541 }
542 // Read combined vg_v in restart file style
543 double moments[5];
544 ptr = moments;
545 xmlAttributes.clear();
546 xmlAttributes.push_back(make_pair("mesh",meshName));
547 xmlAttributes.push_back(make_pair("name","moments"));
548 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,ptr,false) == true) {
549 cerr << "NOTE: Using combined vg_v (all populations!) from restart for plasma frame shifting." << endl;
550 V_bulk[0] = moments[1];
551 V_bulk[0] = moments[2];
552 V_bulk[0] = moments[3];
553 break;
554 }
555 // We should have broken out before or we're doomed
556 cerr << "ERROR: Could not find a usable velocity for plasma frame shift!" << endl;
557 exit(1);
558 break;
559 } while (true);
560
561}
562
563void getB(Real* B,vlsvinterface::Reader& vlsvReader,const string& meshName,const uint64_t& cellID) {
564 //Declarations
565 vlsv::datatype::type cellIdDataType;
566 uint64_t cellIdArraySize, cellIdVectorSize, cellIdDataSize;
567
568 list<pair<string,string> > xmlAttributes;
569 xmlAttributes.push_back(make_pair("mesh",meshName));
570 xmlAttributes.push_back(make_pair("name","CellID"));
571 if (vlsvReader.getArrayInfo("VARIABLE", xmlAttributes, cellIdArraySize, cellIdVectorSize, cellIdDataType, cellIdDataSize) == false) {
572 cerr << "Error " << __FILE__ << " " << __LINE__ << endl;
573 exit(1);
574 }
575
576 // Declare buffers and allocate memory, this is done to read in the cell id location:
577 uint64_t* cellIdBuffer = NULL;
578
579 // Read the array into cellIdBuffer starting from 0 up until cellIdArraySize
580 // which was received from getArrayInfo
581 if (vlsvReader.read("VARIABLE",xmlAttributes,0,cellIdArraySize,cellIdBuffer,true) == false) {
582 cerr << "Error: failed to read cell IDs in " << __FILE__ << ":" << __LINE__ << endl;
583 delete [] cellIdBuffer;
584 exit(1);
585 }
586
587 // Search for the given cellID location, the array in the vlsv file is not ordered depending
588 // on the cell id so the array might look like this,
589 // for instance: [CellId1, CellId7, CellId5, ...] and the variables are saved in the same
590 // order: [CellId1_B_FIELD, CellId7_B_FIELD, CellId5_B_FIELD, ...]
591 uint64_t cellIndex = numeric_limits<uint64_t>::max();
592 for (uint64_t cell=0; cell<cellIdArraySize; ++cell) {
593 // the CellID are not sorted in the array, so we'll have to search
594 // the array -- the CellID is stored in cellId
595 if (cellID == cellIdBuffer[cell]) {
596 //Found the right cell ID, break
597 cellIndex = cell; break;
598 }
599 }
600 delete [] cellIdBuffer; cellIdBuffer = NULL;
601
602 // Check if the cell id was found:
603 if (cellIndex == numeric_limits<uint64_t>::max()) {
604 cerr << "Spatial cell #" << cellID << " not found in " << __FILE__ << ":" << __LINE__ << endl;
605 exit(1);
606 }
607
608 // These are needed to determine the buffer size:
609 vlsv::datatype::type variableDataType;
610 uint64_t variableArraySize, variableVectorSize, variableDataSize;
611
612 // Magnetic field can exists in the file in few different variables.
613 // Here we go with the following priority:
614 // - vg_b_vol
615 // - B_vol
616 // - BGB_vol + PERB_vol
617 // - B
618 // - background_B + perturbed_B
619
620
621 double B1[3] = {0,0,0};
622 double B2[3] = {0,0,0};
623
624 double* B1_ptr = B1;
625 double* B2_ptr = B2;
626
627 if (runDebug == true) cerr << "***** DEBUG INFO FOR getB() *****" << endl;
628
629 bool B_read = true;
630 do {
631 // Attempt to read 'vg_b_vol'
632 B_read = true;
633 xmlAttributes.clear();
634 xmlAttributes.push_back(make_pair("mesh",meshName));
635 xmlAttributes.push_back(make_pair("name","vg_b_vol"));
636 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,B1_ptr,false) == false) B_read = false;
637 if (B_read == true) {
638 if (runDebug == true) cerr << "Using vg_b_vol" << endl;
639 break;
640 }
641
642 // Attempt to read 'vg_b_background_vol' + 'vg_b_perturbed_vol'
643 B_read = true;
644 xmlAttributes.clear();
645 xmlAttributes.push_back(make_pair("mesh",meshName));
646 xmlAttributes.push_back(make_pair("name","vg_b_background_vol"));
647 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,B1_ptr,false) == false) B_read = false;
648 xmlAttributes.clear();
649 xmlAttributes.push_back(make_pair("mesh",meshName));
650 xmlAttributes.push_back(make_pair("name","vg_b_perturbed_vol"));
651 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,B2_ptr,false) == false) B_read = false;
652 if (B_read == true) {
653 if (runDebug == true) cerr << "Using vg_b_background_vol + vg_b_perturbed_vol" << endl;
654 break;
655 }
656
657 // Attempt to read 'B_vol'
658 B_read = true;
659 xmlAttributes.clear();
660 xmlAttributes.push_back(make_pair("mesh",meshName));
661 xmlAttributes.push_back(make_pair("name","B_vol"));
662 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,B1_ptr,false) == false) B_read = false;
663 if (B_read == true) {
664 if (runDebug == true) cerr << "Using B_vol" << endl;
665 break;
666 }
667
668 // Attempt to read 'BGB_vol' + 'PERB_vol'
669 B_read = true;
670 xmlAttributes.clear();
671 xmlAttributes.push_back(make_pair("mesh",meshName));
672 xmlAttributes.push_back(make_pair("name","BGB_vol"));
673 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,B1_ptr,false) == false) B_read = false;
674 xmlAttributes.clear();
675 xmlAttributes.push_back(make_pair("mesh",meshName));
676 xmlAttributes.push_back(make_pair("name","PERB_vol"));
677 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,B2_ptr,false) == false) B_read = false;
678 if (B_read == true) {
679 if (runDebug == true) cerr << "Using BGB_vol + PERB_vol" << endl;
680 break;
681 }
682
683 // Attempt to read variable 'B'
684 B_read = true;
685 xmlAttributes.clear();
686 xmlAttributes.push_back(make_pair("mesh",meshName));
687 xmlAttributes.push_back(make_pair("name","B"));
688 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,B1_ptr,false) == false) B_read = false;
689 if (B_read == true) {
690 if (runDebug == true) cerr << "Using B" << endl;
691 break;
692 }
693
694 // Attempt to read 'background_B' + 'perturbed_B'
695 B_read = true;
696 xmlAttributes.clear();
697 xmlAttributes.push_back(make_pair("mesh",meshName));
698 xmlAttributes.push_back(make_pair("name","background_B"));
699 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,B1_ptr,false) == false) B_read = false;
700 xmlAttributes.clear();
701 xmlAttributes.push_back(make_pair("mesh",meshName));
702 xmlAttributes.push_back(make_pair("name","perturbed_B"));
703 if (vlsvReader.read("VARIABLE",xmlAttributes,cellIndex,1,B2_ptr,false) == false) B_read = false;
704 if (B_read == true) {
705 if (runDebug == true) cerr << "Using background_B + perturbed_B" << endl;
706 break;
707 }
708
709 break;
710 } while (true);
711
712 if (B_read == false) {
713 cerr << "Failed to read magnetic field in " << __FILE__ << " " << __LINE__ << endl;
714 exit(1);
715 }
716
717 for (int i=0; i<3; ++i) B[i] = B1[i] + B2[i];
718
719 if (runDebug == true) {
720 cerr << "B1 = " << B1[0] << '\t' << B1[1] << '\t' << B1[2] << endl;
721 cerr << "B2 = " << B2[0] << '\t' << B2[1] << '\t' << B2[2] << endl;
722 cerr << "B = " << B[0] << '\t' << B[1] << '\t' << B[2] << endl;
723 cerr << endl;
724 }
725}
726
728 vlsvinterface::Reader& vlsvReader,
729 const string& fname,
730 const string& meshName,
731 CellStructure& cellStruct,
732 const uint64_t& cellID,
733 const bool rotate,
734 const bool plasmaFrame,
735 vlsv::Writer& out,
736 const std::string& popName
737 ) {
738 bool success = true;
739
740 // Read velocity mesh metadata for this population
741 if (setVelocityMeshVariables(vlsvReader,cellStruct,popName) == false) {
742 //cerr << "ERROR, failed to read velocity mesh metadata for species '";
743 //cerr << popName << "'" << endl;
744
745 cerr << "Trying older Vlasiator file format..." << endl;
746 if (setVelocityMeshVariables(vlsvReader,cellStruct) == false) {
747 cerr << "ERROR, failed to read velocity mesh metadata in " << __FILE__ << ":" << __LINE__ << endl;
748 success = false;
749 return success;
750 }
751 }
752
753 string outputMeshName = "VelGrid_" + popName;
754 int cellsInBlocksPerDirection = 4;
755
756 // Transformation (translation + rotation) matrix, defaults
757 // to identity matrix. Modified if rotate and/or plasmaFrame are true.
758 Real transform[16];
759 for (int i=0; i<16; ++i) transform[i] = 0;
760 transform[0 ] = 1;
761 transform[5 ] = 1;
762 transform[10] = 1;
763 transform[15] = 1;
764
765 if (plasmaFrame == true) {
766 Real V_bulk[3];
767 getBulkVelocity(V_bulk,vlsvReader,meshName,popName,cellID);
768 applyTranslation(V_bulk,transform);
769 }
770
771 // Write transform matrix (if needed)
772 if (rotate == true) {
773 Real B[3];
774 //Note: allocates memory and stores the vector value into B_ptr
775 getB(B,vlsvReader,meshName,cellID);
776 applyRotation(B,transform);
777 }
778
779 if (plasmaFrame == true || rotate == true) {
780 map<string,string> attributes;
781 attributes["name"] = "transmat";
782 if (out.writeArray("TRANSFORM",attributes,16,1,transform) == false) success = false;
783 }
784
785 // Read velocity block global IDs and write them out
786 std::vector<uint64_t> blockIds;
787 if (vlsvReader.getBlockIds(cellID,blockIds,popName) == false ) {
788 cerr << "Trying older Vlasiator file format..." << endl;
789 if (vlsvReader.getBlockIds(cellID,blockIds,"") == false) {
790 cerr << "ERROR, failed to read IDs at " << __FILE__ << ":" << __LINE__ << endl;
791 success = false;
792 return success;
793 }
794 }
795 const size_t N_blocks = blockIds.size();
796
797 map<string,string> attributes;
798 attributes["name"] = outputMeshName;
799 attributes["type"] = vlsv::mesh::STRING_UCD_AMR;
800 stringstream ss;
801 ss << (uint32_t)cellStruct.maxVelRefLevel;
802 attributes["max_refinement_level"] = ss.str();
803 attributes["geometry"] = vlsv::geometry::STRING_CARTESIAN;
804 if (plasmaFrame == true || rotate == true) attributes["transform"] = "transmat";
805
806 if (out.writeArray("MESH",attributes,blockIds.size(),1,&(blockIds[0])) == false) success = false;
807
808 attributes["name"] = "VelBlocks_" + popName;
809 if (out.writeArray("MESH",attributes,blockIds.size(),1,&(blockIds[0])) == false) success = false;
810
811 attributes.clear();
812
813 // Create array of phase-space mesh cell IDs, this is needed to make
814 // vlsvdiff work with extracted velocity meshes
815 std::vector<uint64_t> cellIDs(blockIds.size()*64);
816 for (size_t b=0; b<blockIds.size(); ++b) {
817 for (int c=0; c<64; ++c) cellIDs[b*64+c] = blockIds[b]*64+c;
818 }
819 attributes["mesh"] = outputMeshName;
820 attributes["name"] = "CellID";
821 if (out.writeArray("VARIABLE",attributes,cellIDs.size(),1,&(cellIDs[0])) == false) success = false;
822 attributes.clear();
823
824 // Make domain size array
825 uint64_t domainSize[2];
826 domainSize[0] = blockIds.size();
827 domainSize[1] = 0;
828 attributes["mesh"] = outputMeshName;
829 if (out.writeArray("MESH_DOMAIN_SIZES",attributes,1,2,domainSize) == false) success = false;
830 {
831 std::vector<uint64_t> ().swap(blockIds);
832 }
833
834 attributes["mesh"] = "VelBlocks_" + popName;
835 if (out.writeArray("MESH_DOMAIN_SIZES",attributes,1,2,domainSize) == false) success = false;
836
837 // Make bounding box array
838 uint64_t bbox[6];
839 bbox[0] = cellStruct.vcell_bounds[0];
840 bbox[1] = cellStruct.vcell_bounds[1];
841 bbox[2] = cellStruct.vcell_bounds[2];
842
843 bbox[3] = 1;
844 bbox[4] = 1;
845 bbox[5] = 1;
846 attributes["mesh"] = "VelBlocks_" + popName;
847 if (out.writeArray("MESH_BBOX",attributes,6,1,bbox) == false) success = false;
848
849 bbox[3] = cellsInBlocksPerDirection;
850 bbox[4] = cellsInBlocksPerDirection;
851 bbox[5] = cellsInBlocksPerDirection;
852 const uint32_t blockSize = bbox[3]*bbox[4]*bbox[5];
853 attributes["mesh"] = outputMeshName;
854 if (out.writeArray("MESH_BBOX",attributes,6,1,bbox) == false) success = false;
855
856 // Make node coordinate arrays
857 std::vector<float> coords;
858 for (int crd=0; crd<3; ++crd) {
859 // crd enumerates the coordinate: 0 = vx, 1 = vy, 2 = vz
860 coords.clear();
861
862 // Generate node coordinates
863 for (size_t i=0; i<bbox[crd]; ++i) {
864 for (size_t j=0; j<bbox[crd+3]; ++j) {
865 coords.push_back( cellStruct.min_vcoordinates[crd] + i*cellStruct.vblock_length[crd] + j*cellStruct.vblock_length[crd]/bbox[crd+3] );
866 }
867 }
868 coords.push_back( cellStruct.min_vcoordinates[crd] + bbox[crd]*cellStruct.vblock_length[crd] );
869
870 // Write them to output file
871 string arrayName;
872 if (crd == 0) arrayName = "MESH_NODE_CRDS_X";
873 else if (crd == 1) arrayName = "MESH_NODE_CRDS_Y";
874 else if (crd == 2) arrayName = "MESH_NODE_CRDS_Z";
875
876 if (coords.size() != bbox[crd]*bbox[crd+3]+1) {
877 cerr << "ERROR incorrect node coordinates at " << __FILE__ << " " << __LINE__ << endl;
878 }
879
880 attributes["mesh"] = outputMeshName;
881 if (out.writeArray(arrayName,attributes,coords.size(),1,&(coords[0])) == false) {
882 cerr << "ERROR, failed to write velocity grid coordinates in " << __FILE__ << ":" << __LINE__ << endl;
883 success = false;
884 }
885 }
886 {
887 std::vector<float> ().swap(coords);
888 }
889
890 for (int crd=0; crd<3; ++crd) {
891 coords.clear();
892 for (size_t i=0; i<bbox[crd]; ++i) {
893 coords.push_back( cellStruct.min_vcoordinates[crd] + i*cellStruct.vblock_length[crd] );
894 }
895 coords.push_back( cellStruct.min_vcoordinates[crd] + bbox[crd]*cellStruct.vblock_length[crd] );
896
897 string arrayName;
898 if (crd == 0) arrayName = "MESH_NODE_CRDS_X";
899 else if (crd == 1) arrayName = "MESH_NODE_CRDS_Y";
900 else if (crd == 2) arrayName = "MESH_NODE_CRDS_Z";
901
902 attributes["mesh"] = "VelBlocks_" + popName;
903 if (out.writeArray(arrayName,attributes,coords.size(),1,&(coords[0])) == false) {
904 cerr << "ERROR, failed to write velocity block coordinates in " << __FILE__ << ":" << __LINE__ << endl;
905 success = false;
906 }
907 }
908 {
909 std::vector<float> ().swap(coords);
910 }
911
912 // Write dummy ghost zone data (not applicable here):
913 uint64_t dummy;
914 attributes["mesh"] = outputMeshName;
915 if (out.writeArray("MESH_GHOST_LOCALIDS",attributes,domainSize[1],1,&dummy) == false) {
916 cerr << "ERROR, failed to write ghost cell local IDs in " << __FILE__ << ":" << __LINE__ << endl;
917 success = false;
918 }
919 if (out.writeArray("MESH_GHOST_DOMAINS",attributes,domainSize[1],1,&dummy) == false) {
920 cerr << "ERROR, failed to write ghost cell domains in " << __FILE__ << ":" << __LINE__ << endl;
921 success = false;
922 }
923
924 attributes["mesh"] = "VelBlocks_" + popName;
925 if (out.writeArray("MESH_GHOST_LOCALIDS",attributes,domainSize[1],1,&dummy) == false) {
926 cerr << "ERROR, failed to write ghost cell local IDs in " << __FILE__ << ":" << __LINE__ << endl;
927 success = false;
928 }
929 if (out.writeArray("MESH_GHOST_DOMAINS",attributes,domainSize[1],1,&dummy) == false) {
930 cerr << "ERROR, failed to write ghost cell domains in " << __FILE__ << ":" << __LINE__ << endl;
931 success = false;
932 }
933
934 // ***** Convert variables ***** //
935
936 // Get the names of velocity mesh variables. NOTE: This will find _all_ particle populations
937 // which are stored in their separate meshes.
938 set<string> blockVarNames;
939 const string attributeName = "name";
940 if (vlsvReader.getUniqueAttributeValues( "BLOCKVARIABLE", attributeName, blockVarNames) == false) {
941 cerr << "ERROR, FAILED TO GET UNIQUE ATTRIBUTE VALUES AT " << __FILE__ << " " << __LINE__ << endl;
942 }
943
944 //Writing VLSV file
945 if (success == true) {
946 for (set<string>::iterator it = blockVarNames.begin(); it != blockVarNames.end(); ++it) {
947 // Only accept the population that belongs to this mesh
948 if (*it != popName) continue;
949
950 list<pair<string, string> > attribs;
951 attribs.push_back(make_pair("name", *it));
952 attribs.push_back(make_pair("mesh", meshName));
953 datatype::type dataType;
954 uint64_t arraySize, vectorSize, dataSize;
955 if (vlsvReader.getArrayInfo("BLOCKVARIABLE", attribs, arraySize, vectorSize, dataType, dataSize) == false) {
956 cerr << "Could not read BLOCKVARIABLE array info in " << __FILE__ << ":" << __LINE__ << endl;
957 return false;
958 }
959
960 char* buffer = new char[N_blocks * vectorSize * dataSize];
961 if (vlsvReader.readArray("BLOCKVARIABLE", attribs, vlsvReader.getBlockOffset(cellID), N_blocks, buffer) == false) {
962 cerr << "ERROR could not read block variable in " << __FILE__ << ":" << __LINE__ << endl;
963 delete[] buffer;
964 return success;
965 }
966
967 attributes["name"] = *it;
968 attributes["mesh"] = outputMeshName;
969 if (out.writeArray("VARIABLE",
971 vlsv::getStringDatatype(dataType),
972 N_blocks * blockSize,
973 vectorSize/blockSize,
974 dataSize,
975 buffer) == false) success = false;
976
977 delete [] buffer; buffer = NULL;
978 }
979 }
980
981 vlsvReader.clearCellsWithBlocks();
982 return success;
983}
984
985//Creates a cell id list of type std::unordered set and saves it in the input parameters
986//Input:
987//[0] vlsvReader -- some vlsv reader with a file open
988//Output:
989//[0] cellIdList -- Inputs a list of cell ids here
990//[1] sizeOfCellIdList -- Inputs the size of the cell id list here
991template <class T>
992bool createCellIdList( T & vlsvReader, unordered_set<uint64_t> & cellIdList ) {
993 if( cellIdList.empty() == false ) {
994 cerr << "ERROR, PASSED A NON-EMPTY CELL ID LIST AT " << __FILE__ << " " << __LINE__ << endl;
995 return false;
996 }
997 //meshname should be "SpatialGrid" and tag should be "CELLSWITHBLOCKS"
998 const string meshName = "SpatialGrid";
999 const string tagName = "CELLSWITHBLOCKS";
1000 //For reading in attributes
1001 list< pair<string, string> > attributes;
1002 attributes.push_back( make_pair("mesh", meshName) );
1003
1004 //Get a list of possible CellIDs from the file under CELLSWITHBLOCKS:
1005 //Declare vectorSize, arraySize, .., so we know the size of the array we're going to read:
1006 datatype::type dataType;
1007 uint64_t arraySize, vectorSize, dataSize; //used to store info on the data we want to retrieve (needed for readArray)
1008 //Read arraySize, vectorSize, dataType and dataSize and store them with getArrayInfo:
1009 if (vlsvReader.getArrayInfo( tagName, attributes, arraySize, vectorSize, dataType, dataSize ) == false) {
1010 cerr << "Could not find array " << tagName << " at: " << __FILE__ << " " << __LINE__ << endl;
1011 exit(1); //error, terminate program
1012 return false; //Shouldn't actually even get this far but whatever
1013 }
1014 //Check to make sure that the vectorSize is 1 as the CellIdList should be (Assuming so later on):
1015 if( vectorSize != 1 ) {
1016 cerr << tagName << "'s vector size is not 1 at: " << __FILE__ << " " << __LINE__ << endl;
1017 exit(1);
1018 return false;
1019 }
1020
1021 //We now have the arraySize and everything else needed
1022 //Create a buffer -- the size is determined by the data we received from getArrayInfo
1023 char * buffer = new char[arraySize * vectorSize * dataSize];
1024 const int beginningPoint = 0; //Read from the beginning ( 0 ) up to arraySize ( arraySize )
1025 //Read data into the buffer with readArray:
1026 if (vlsvReader.readArray(tagName, attributes, beginningPoint, arraySize, buffer) == false) {
1027 cerr << "Failed to read block metadata for mesh '" << meshName << "' at: ";
1028 cerr << __FILE__ << " " << __LINE__ << endl;
1029 delete[] buffer;
1030 exit(1);
1031 return false;
1032 }
1033
1034
1035 //Reinterpret the buffer and point cellIdList in the right direction:
1036 uint64_t * _cellIdList = reinterpret_cast<uint64_t*>(buffer);
1037 //Reserve space for the cell id list:
1038 cellIdList.rehash( (uint64_t)(arraySize * 1.25) );
1039 for( uint64_t i = 0; i < arraySize; ++i ) {
1040 cellIdList.insert( (uint64_t)( _cellIdList[i] ) );
1041 }
1042 delete[] buffer;
1043 return true;
1044}
1045
1059 vlsvinterface::Reader& vlsvReader,
1060 const string& fname,
1061 const string& meshName,
1062 CellStructure& cellStruct,
1063 const uint64_t& cellID,
1064 const bool rotate,
1065 const bool plasmaFrame
1066 ) {
1067 // Read names of all existing particle species
1068 set<string> popNames;
1069 if (vlsvReader.getUniqueAttributeValues("BLOCKIDS","name",popNames) == false) {
1070 cerr << "ERROR could not read population names in " << __FILE__ << ":" << __LINE__ << endl;
1071 return false;
1072 }
1073
1074 if (runDebug == true) {
1075 cerr << "Found " << popNames.size() << " particle populations" << endl;
1076 }
1077
1078 // Open output file
1079 vlsv::Writer out;
1080 if (out.open(fname,MPI_COMM_SELF,0) == false) {
1081 cerr << "ERROR, failed to open output file with vlsv::Writer at " << __FILE__ << " " << __LINE__ << endl;
1082 return false;
1083 }
1084
1085 bool success = true;
1086 if (popNames.size() > 0) {
1087 for (set<string>::iterator it=popNames.begin(); it!=popNames.end(); ++it) {
1088 if (runDebug == true) cerr << "Population '" << *it << "' meshName '" << meshName << "'" << endl;
1089 if (vlsvReader.setCellsWithBlocks(meshName,*it) == false) {success = false; continue;}
1090 if (convertVelocityBlocks2(vlsvReader,fname,meshName,cellStruct,cellID,rotate,plasmaFrame,out,*it) == false) success = false;
1091 }
1092 } else {
1093 if (runDebug == true) cerr << "Extracting old-style population 'avgs'" << endl;
1094 if (vlsvReader.setCellsWithBlocks(meshName,"") == false) {success = false;}
1095 if (convertVelocityBlocks2(vlsvReader,fname,meshName,cellStruct,cellID,rotate,plasmaFrame,out,"avgs") == false) success = false;
1096 }
1097
1098 out.close();
1099 return success;
1100}
1101
1102//Calculates the cell coordinates and outputs into *coordinates
1103//NOTE: ASSUMING COORDINATES IS NOT NULL AND IS OF SIZE 3
1104//Input:
1105//[0] CellStructure cellStruct -- A struct for holding cell information. Has the cell length in x,y,z direction, for example
1106//[1] uint64_t cellId -- Some given cell id
1107//Output:
1108//[0] Real * coordinates -- Some coordinates x, y, z (NOTE: the vector size should be 3!)
1109void getCellCoordinates( const CellStructure & cellStruct, const uint64_t cellId, Real * coordinates ) {
1110 //Check for null pointer
1111 if( !coordinates ) {
1112 cerr << "Passed invalid pointer at: " << __FILE__ << " " << __LINE__ << endl;
1113 exit(1);
1114 }
1115 //Calculate the cell coordinates in block coordinates (so in the cell grid where the coordinates are integers)
1116 uint64_t currentCellCoordinate[3];
1117 //Note: cell_bounds is a variable that tells the length of a cell in x, y or z direction (depending on the index)
1118 //cellStruct is a struct that holds info on the cell structure used in simulation (such as the length of the cell and the mininum
1119 //value of x within the cell grid)
1120 currentCellCoordinate[0] = cellId % cellStruct.cell_bounds[0];
1121 currentCellCoordinate[1] = ((cellId - currentCellCoordinate[0]) / cellStruct.cell_bounds[0]) % cellStruct.cell_bounds[1];
1122 currentCellCoordinate[2] = ((cellId - cellStruct.cell_bounds[0]*currentCellCoordinate[1]) / (cellStruct.cell_bounds[0]*cellStruct.cell_bounds[1]));
1123 //the currentCellCoordinate is always off by one -- This is just a matter of how stuff has been calculated. If cell bounds and
1124 //other stuff were defined slightly in other parts of this code differently, this would not be needed.
1125 currentCellCoordinate[0] -= 1;
1126 //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)
1127 coordinates[0] = cellStruct.min_coordinates[0] + currentCellCoordinate[0] * cellStruct.cell_length[0];
1128 coordinates[1] = cellStruct.min_coordinates[1] + currentCellCoordinate[1] * cellStruct.cell_length[1];
1129 coordinates[2] = cellStruct.min_coordinates[2] + currentCellCoordinate[2] * cellStruct.cell_length[2];
1130 //all done
1131 return;
1132}
1133
1134//Searches for the closest cell id to the given coordinates from a list of cell ids and returns it
1135//Input:
1136//[0] CellStructure cellStruct -- a struct that holds info on cell structure
1137//[1] uint64_t * cellIdList -- Some list of cell ids (Note: Could use a vector here)
1138//[2] Real * coordinates, -- Some coordinates x, y, z (Note: Could use std::array here)
1139//[3] uint64_t sizeOfCellIdList -- Size of cellIdList (Note: This would not be needed if a vector was used)a
1140//Output:
1141//[0] Returns the closest cell id to the given coordinates
1142uint64_t searchForBestCellId( const CellStructure & cellStruct,
1143 const uint64_t * cellIdList,
1144 const Real * coordinates,
1145 const uint64_t sizeOfCellIdList ) {
1146 //Check for null pointer:
1147 if( !cellIdList || !coordinates ) {
1148 cerr << "Error at: ";
1149 cerr << __FILE__ << " " << __LINE__;
1150 cerr << ", passed a null pointer to searchForBestCellId" << endl;
1151 exit(1);
1152 return 0;
1153 }
1154 //Create variables to help iterate through cellIdList. (Used to keep track of the best cell id and best distance so far)
1155 Real bestDistance = numeric_limits<Real>::max();
1156 Real bestCellId = numeric_limits<uint64_t>::max();
1157 //Iterate through the list of cell id candidates ( cell ids with distribution )
1158 for( uint64_t i = 0; i < sizeOfCellIdList; ++i ) {
1159 //Get coordinates from the cell currently being handled in the iteration:
1160 const uint64_t currentCell = cellIdList[i];
1161 //Create cellCoordinate and store the current cell id's coordinates in there
1162 const size_t _size = 3;
1163 Real cellCoordinate[_size];
1164 //Stores the current cell's coordinates into cellCoordinate
1165 getCellCoordinates( cellStruct, currentCell, cellCoordinate );
1166 //Calculate distance from cell coordinates to input coordinates
1167 Real dist = (
1168 (cellCoordinate[0] - coordinates[0]) * (cellCoordinate[0] - coordinates[0])
1169 + (cellCoordinate[1] - coordinates[1]) * (cellCoordinate[1] - coordinates[1])
1170 + (cellCoordinate[2] - coordinates[2]) * (cellCoordinate[2] - coordinates[2])
1171 );
1172 //if the distance from the given coordinates to the cell coordinates is the best so far, set that cell id as the best cell id
1173 if( bestDistance > dist ) {
1174 bestDistance = dist;
1175 bestCellId = currentCell;
1176 }
1177 }
1178 //return the best cell id:
1179 return bestCellId;
1180}
1181
1182//Searches for the closest cell id to the given coordinates from a list of cell ids and returns it
1183//Input:
1184//[0] CellStructure cellStruct -- a struct that holds info on cell structure
1185//[1] cellIdList -- Some list of cell ids
1186//[2] coordinates, -- Some coordinates x, y, z
1187//Output:
1188//[0] Returns the closest cell id to the given coordinates
1189uint64_t searchForBestCellId( const CellStructure & cellStruct,
1190 const unordered_set<uint64_t> & cellIdList,
1191 const std::array<Real, 3> coordinates ) {
1192 //Check for null pointer:
1193 if( coordinates.empty() ) {
1194 cerr << "ERROR, PASSED AN EMPTY COORDINATES AT " << __FILE__ << " " << __LINE__ << endl;
1195 exit(1);
1196 }
1197 if( cellIdList.empty() ) {
1198 cerr << "ERROR, PASSED AN EMPTY CELL ID LIST AT " << __FILE__ << " " << __LINE__ << endl;
1199 exit(1);
1200 }
1201
1202 //Get the cell id corresponding to the given coordinates:
1203 int cellCoordinates[3];
1204 for( unsigned int i = 0; i < 3; ++i ) {
1205 //Note: Cell coordinates work like this:
1206 //cell id = z * (num. of cell in y-direction) * (num. of cell in z-direction) + y * (num. of cell in x-direction) + x
1207 cellCoordinates[i] = floor((coordinates[i] - cellStruct.min_coordinates[i]) / cellStruct.cell_length[i]);
1208 if( cellCoordinates[i] < 0 ) {
1209 cerr << "Coordinates out of bounds at " << __FILE__ << " " << __LINE__ << endl;
1210 return numeric_limits<uint64_t>::max();
1211 }
1212 }
1213
1214 //Return the cell id at cellCoordinates:
1215 //Note: In vlasiator, the cell ids start from 1 hence the '+ 1'
1216
1217 return ( (uint64_t)(
1218 cellCoordinates[2] * cellStruct.cell_bounds[1] * cellStruct.cell_bounds[0]
1219 + cellCoordinates[1] * cellStruct.cell_bounds[0]
1220 + cellCoordinates[0] + 1
1221 ) );
1222}
1223
1228bool setVelocityMeshVariables(vlsv::Reader& vlsvReader,CellStructure& cellStruct) {
1229 bool success = true;
1230
1231 // Read the velocity mesh bounding box, i.e., maximum number of
1232 // blocks per coordinate direction.
1233 uint32_t vcell_bounds[3];
1234 if (vlsvReader.readParameter("vxblocks_ini",cellStruct.vcell_bounds[0]) == false) {
1235 cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << ":" << __LINE__ << endl;
1236 success = false;
1237 }
1238 if (vlsvReader.readParameter("vyblocks_ini",cellStruct.vcell_bounds[1]) == false) {
1239 cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << ":" << __LINE__ << endl;
1240 success = false;
1241 }
1242 if (vlsvReader.readParameter("vzblocks_ini",cellStruct.vcell_bounds[2]) == false) {
1243 cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << ":" << __LINE__ << endl;
1244 success = false;
1245 }
1246
1247 // Read velocity mesh min/max extents.
1248 Real vx_min,vx_max,vy_min,vy_max,vz_min,vz_max;
1249 if (vlsvReader.readParameter("vxmin",vx_min) == false) {
1250 cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << ":" << __LINE__ << endl;
1251 success = false;
1252 }
1253 if (vlsvReader.readParameter("vxmax",vx_max) == false) {
1254 cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << ":" << __LINE__ << endl;
1255 success = false;
1256 }
1257 if (vlsvReader.readParameter("vymin",vy_min) == false) {
1258 cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << ":" << __LINE__ << endl;
1259 success = false;
1260 }
1261 if (vlsvReader.readParameter("vymax",vy_max) == false) {
1262 cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << ":" << __LINE__ << endl;
1263 success = false;
1264 }
1265 if (vlsvReader.readParameter("vzmin",vz_min) == false) {
1266 cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1267 success = false;
1268 }
1269 if (vlsvReader.readParameter("vzmax",vz_max) == false) {
1270 cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1271 success = false;
1272 }
1273
1274 // Calculate velocity phase-space cell lengths.
1275 const Real vx_length = vx_max - vx_min;
1276 const Real vy_length = vy_max - vy_min;
1277 const Real vz_length = vz_max - vz_min;
1278 cellStruct.vblock_length[0] = ( vx_length / (Real)(cellStruct.vcell_bounds[0]) );
1279 cellStruct.vblock_length[1] = ( vy_length / (Real)(cellStruct.vcell_bounds[1]) );
1280 cellStruct.vblock_length[2] = ( vz_length / (Real)(cellStruct.vcell_bounds[2]) );
1281
1282 // Set velocity mesh min coordinate values.
1283 cellStruct.min_vcoordinates[0] = vx_min;
1284 cellStruct.min_vcoordinates[1] = vy_min;
1285 cellStruct.min_vcoordinates[2] = vz_min;
1286
1287 if (runDebug == true && success == true) {
1288 cerr << "Pop 'avgs'" << endl;
1289 cerr << "\t mesh limits : ";
1290 cerr << vx_min << '\t' << vx_max << '\t' << vy_min << '\t' << vy_max << '\t' << vz_min << '\t' << vz_max << endl;
1291 cerr << "\t mesh bbox size: " << cellStruct.vcell_bounds[0] << ' ' << cellStruct.vcell_bounds[1] << ' ' << cellStruct.vcell_bounds[2] << endl;
1292 cerr << "\t cell sizes : " << cellStruct.vblock_length[0] << '\t' << cellStruct.vblock_length[1] << '\t' << cellStruct.vblock_length[2] << endl;
1293 cerr << "\t max ref level : " << cellStruct.maxVelRefLevel << endl;
1294 }
1295
1296 return success;
1297}
1298
1304bool setVelocityMeshVariables(vlsv::Reader& vlsvReader,CellStructure& cellStruct,
1305 const std::string& popName) {
1306 bool success = true;
1307
1308 Real vx_min=0,vx_max=0,vy_min=0,vy_max=0,vz_min=0,vz_max=0;
1309
1310 // Read node coordinate arrays to figure out mesh extents
1311 for (int crd=0; crd<3; ++crd) {
1312 list<pair<string,string> > attribsIn;
1313 attribsIn.push_back(make_pair("mesh",popName));
1314
1315 string tagName;
1316 if (crd == 0) tagName = "MESH_NODE_CRDS_X";
1317 if (crd == 1) tagName = "MESH_NODE_CRDS_Y";
1318 if (crd == 2) tagName = "MESH_NODE_CRDS_Z";
1319
1320 // Read node coordinate array info
1321 map<string,string> attribsOut;
1322 if (vlsvReader.getArrayAttributes(tagName,attribsIn,attribsOut) == false) {
1323 success = false; continue;
1324 }
1325
1326 // Figure out the number of nodes in this coordinate direction
1327 uint64_t N_nodes = 0;
1328 map<string,string>::const_iterator it = attribsOut.find("arraysize");
1329 if (it != attribsOut.end()) N_nodes = atol(it->second.c_str());
1330
1331 // Read node coordinates
1332 Real* crds = NULL;
1333 if (vlsvReader.read(tagName,attribsIn,0,N_nodes,crds,true) == false) success = false;
1334
1335 if (crd == 0) { vx_min = crds[0]; vx_max = crds[N_nodes-1]; }
1336 if (crd == 1) { vy_min = crds[0]; vy_max = crds[N_nodes-1]; }
1337 if (crd == 2) { vz_min = crds[0]; vz_max = crds[N_nodes-1]; }
1338 delete [] crds; crds = NULL;
1339 }
1340
1341 // Read the velocity mesh bounding box
1342 list<pair<string,string> > attribs;
1343 attribs.push_back(make_pair("mesh",popName));
1344 uint64_t velMeshBbox[6];
1345 uint64_t* velMeshBbox_ptr = velMeshBbox;
1346 if (vlsvReader.read("MESH_BBOX",attribs,0,6,velMeshBbox_ptr,false) == false) {
1347 cerr << "Failed to read velocity mesh BBOX in " << __FILE__ << ":" << __LINE__ << endl;
1348 success = false;
1349 }
1350
1351 //Set the cell structure properly:
1352 for (int i = 0; i<3; ++i) {
1353 cellStruct.vcell_bounds[i] = velMeshBbox[i];
1354 }
1355
1356 //Calculate the velocity block physical size (in m/s)
1357 Real vx_length = vx_max - vx_min;
1358 Real vy_length = vy_max - vy_min;
1359 Real vz_length = vz_max - vz_min;
1360 cellStruct.vblock_length[0] = ( vx_length / (Real)(velMeshBbox[0]) );
1361 cellStruct.vblock_length[1] = ( vy_length / (Real)(velMeshBbox[1]) );
1362 cellStruct.vblock_length[2] = ( vz_length / (Real)(velMeshBbox[2]) );
1363
1364 //Calculate the minimum coordinates for velocity cells
1365 cellStruct.min_vcoordinates[0] = vx_min;
1366 cellStruct.min_vcoordinates[1] = vy_min;
1367 cellStruct.min_vcoordinates[2] = vz_min;
1368
1369 // By default set an unrefined velocity mesh. Then check if the max refinement level
1370 // was actually given as a parameter.
1371 uint32_t dummyUInt;
1372 cellStruct.maxVelRefLevel = 0;
1373 map<string,string> attribsOut;
1374 vlsvReader.getArrayAttributes("MESH_BBOX",attribs,attribsOut);
1375 if (attribsOut.find("max_velocity_ref_level") != attribsOut.end()) {
1376 cellStruct.maxVelRefLevel = atoi(attribsOut["max_velocity_ref_level"].c_str());
1377 }
1378
1379 if (runDebug == true && success == true) {
1380 cerr << "Pop '" << popName << "'" << endl;
1381 cerr << "\t mesh limits : ";
1382 cerr << vx_min << '\t' << vx_max << '\t' << vy_min << '\t' << vy_max << '\t' << vz_min << '\t' << vz_max << endl;
1383 cerr << "\t mesh bbox size: " << velMeshBbox[0] << ' ' << velMeshBbox[1] << ' ' << velMeshBbox[2] << endl;
1384 cerr << "\t cell sizes : " << cellStruct.vblock_length[0] << '\t' << cellStruct.vblock_length[1] << '\t' << cellStruct.vblock_length[2] << endl;
1385 cerr << "\t max ref level : " << cellStruct.maxVelRefLevel << endl;
1386 }
1387
1388 return success;
1389}
1390
1396bool setSpatialCellVariables(Reader& vlsvReader,CellStructure& cellStruct) {
1397 bool success = true;
1398
1399 // Get x_min, x_max, y_min, y_max, etc so that we know where the given cell
1400 // id is in (loadParameter returns char*, hence the cast)
1401 // Note: Not actually sure if these are Real valued or not
1402 Real x_min,x_max,y_min,y_max,z_min,z_max;
1403
1404 //Read in the parameter:
1405 if( vlsvReader.readParameter( "xmin", x_min ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1406 if( vlsvReader.readParameter( "xmax", x_max ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1407 if( vlsvReader.readParameter( "ymin", y_min ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1408 if( vlsvReader.readParameter( "ymax", y_max ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1409 if( vlsvReader.readParameter( "zmin", z_min ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1410 if( vlsvReader.readParameter( "zmax", z_max ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1411
1412 //Number of cells in x, y, z directions (used later for calculating where in the cell coordinates the given
1413 //coordinates are) (Done in getCellCoordinates)
1414 //There's x, y and z coordinates so the number of different coordinates is 3:
1415 const short int NumberOfCoordinates = 3;
1416 uint64_t cell_bounds[NumberOfCoordinates];
1417
1418 //Get the number of spatial cells in x,y,z direction from the file:
1419 //x-direction
1420 if( vlsvReader.readParameter( "xcells_ini", cell_bounds[0] ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1421 //y-direction
1422 if( vlsvReader.readParameter( "ycells_ini", cell_bounds[1] ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1423 //z-direction
1424 if( vlsvReader.readParameter( "zcells_ini", cell_bounds[2] ) == false ) cerr << "FAILED TO READ PARAMETER AT " << __FILE__ << " " << __LINE__ << endl;
1425
1426 //Now we have the needed variables, so let's calculate how much in one block equals in length:
1427 //Total length of x, y, z:
1428 Real x_length = x_max - x_min;
1429 Real y_length = y_max - y_min;
1430 Real z_length = z_max - z_min;
1431
1432 //Set the cell structure properly:
1433 for( int i = 0; i < NumberOfCoordinates; ++i ) {
1434 cellStruct.cell_bounds[i] = cell_bounds[i];
1435 }
1436 //Calculate the spatial cell physical size (in m)
1437 cellStruct.cell_length[0] = ( x_length / (Real)(cell_bounds[0]) );
1438 cellStruct.cell_length[1] = ( y_length / (Real)(cell_bounds[1]) );
1439 cellStruct.cell_length[2] = ( z_length / (Real)(cell_bounds[2]) );
1440
1441 //Calculate the minimum coordinates
1442 cellStruct.min_coordinates[0] = x_min;
1443 cellStruct.min_coordinates[1] = y_min;
1444 cellStruct.min_coordinates[2] = z_min;
1445
1446 for( int i = 0; i < 3; ++i ) {
1447 if( cellStruct.cell_length[i] == 0 || cellStruct.cell_bounds[i] == 0) {
1448 cerr << "ERROR, ZERO CELL LENGTH OR CELL_BOUNDS AT " << __FILE__ << " " << __LINE__ << endl;
1449 exit(1);
1450 }
1451 }
1452
1453 return success;
1454}
1455
1456//Returns a cell id based on some given coordinates
1457//Returns numeric_limits<uint64_t>::max(), if the distance from the coordinates to cell id is larger than max_distance
1458//Input:
1459//[0] vlsv::Reader& vlsvReader -- Some vlsvReader (with a file open)
1460//[1] Real * coords -- Some given coordinates (in this file the coordinates are retrieved from the user as an input)
1461//Note: Assuming coords is a pointer of size 3
1462//[2] max_distance -- Max allowed distance between the given coordinates *coords and the returned cell id's coordinates
1463//Output:
1464//[0] Returns the cell id in uint64_t
1465uint64_t getCellIdFromCoords( const CellStructure & cellStruct,
1466 const unordered_set<uint64_t> cellIdList,
1467 const std::array<Real, 3> coords) {
1468 if( coords.empty() ) {
1469 cerr << "ERROR, PASSED AN EMPTY STD::ARRAY FOR COORDINATES AT " << __FILE__ << " " << __LINE__ << endl;
1470 }
1471
1472
1473 //Check for empty vectors
1474 if( cellIdList.empty() ) {
1475 cerr << "Invalid cellIdList at " << __FILE__ << " " << __LINE__ << endl;
1476 exit(1);
1477 }
1478 if( coords.empty() ) {
1479 cerr << "Invalid coords at " << __FILE__ << " " << __LINE__ << endl;
1480 exit(1);
1481 }
1482
1483
1484 //Now pick the closest cell id to the given coordinates:
1485 uint64_t cellId = searchForBestCellId( cellStruct, cellIdList, coords );
1486
1487 //Check to make sure the cell id has distribution (It does if it's in the list of cell ids)
1488 unordered_set<uint64_t>::const_iterator foundCellId = cellIdList.find( cellId );
1489 if( foundCellId == cellIdList.end() ) {
1490 //Didn't find the cell id from the list of possible cell ids so return numerical limit:
1491 return numeric_limits<uint64_t>::max();
1492 }
1493
1494 //Everything ok, return the cell id:
1495 return cellId;
1496}
1497
1498//Prints out the usage message
1500 cout << endl;
1501 cout << "USAGE: ./vlsvextract <file name mask> <options>" << endl;
1502 cout << endl;
1503 cout << "To get a list of options use --help" << endl;
1504 cout << endl;
1505}
1506
1507//Used in main() to retrieve options (returns false if something goes wrong)
1508//Input:
1509//[0] int argn -- number of arguments in args
1510//[1] char *args -- arguments
1511//Output:
1512//[0] UserOptions & mainOptions -- Saves all the options in this class
1513bool retrieveOptions( const int argn, char *args[], UserOptions & mainOptions ) {
1514 //Get variables from mainOptions
1515 bool & getCellIdFromCoordinates = mainOptions.getCellIdFromCoordinates;
1516 bool & getCellIdFromInput = mainOptions.getCellIdFromInput;
1517 bool & getCellIdFromLine = mainOptions.getCellIdFromLine;
1518 bool & rotateVectors = mainOptions.rotateVectors;
1519 bool & plasmaFrame = mainOptions.plasmaFrame;
1520 uint64_t & cellId = mainOptions.cellId;
1521 std::vector<uint64_t> & cellIdList = mainOptions.cellIdList;
1522 uint32_t & numberOfCoordinatesInALine = mainOptions.numberOfCoordinatesInALine;
1523 std::vector<string> & outputDirectoryPath = mainOptions.outputDirectoryPath;
1524 std::array<Real, 3> & coordinates = mainOptions.coordinates;
1525 std::array<Real, 3> & point1 = mainOptions.point1;
1526 std::array<Real, 3> & point2 = mainOptions.point2;
1527
1528 //By default every bool input should be false and vectors should be empty
1529 if( getCellIdFromCoordinates == true || rotateVectors == true || plasmaFrame == true || getCellIdFromInput == true || getCellIdFromLine == true || outputDirectoryPath.empty() == false ) {
1530 cerr << "Error at: " << __FILE__ << " " << __LINE__ << ", invalid arguments in retrieveOptions()" << endl;
1531 return false;
1532 }
1533 try {
1534 //Create an options_description
1535 po::options_description desc("Options");
1536 //Add options -- cellID takes input of type uint64_t and coordinates takes a Real-valued std::vector
1537 desc.add_options()
1538 ("help", "display help")
1539 ("debug", "write debugging info to stderr")
1540 ("cellid", po::value<uint64_t>(), "Set cell id")
1541 ("cellidlist", po::value< std::vector<uint64_t>>()->multitoken(), "Set list of cell ids")
1542 ("rotate", "Rotate velocities so that they face z-axis")
1543 ("plasmaFrame", "Shift the distribution so that the bulk velocity is 0")
1544 ("coordinates", po::value< std::vector<Real> >()->multitoken(), "Set spatial coordinates x y z")
1545 ("unit", po::value<string>(), "Sets the units. Options: re, km, m (OPTIONAL)")
1546 ("point1", po::value< std::vector<Real> >()->multitoken(), "Set the starting point x y z of a line")
1547 ("point2", po::value< std::vector<Real> >()->multitoken(), "Set the ending point x y z of a line")
1548 ("pointamount", po::value<unsigned int>(), "Number of points along a line (OPTIONAL)")
1549 ("outputdirectory", po::value< std::vector<string> >(), "The directory where the file is saved (default current folder) (OPTIONAL)");
1550
1551 //For mapping input
1552 po::variables_map vm;
1553 //Store input into vm (Don't allow short options)
1554 po::store(po::parse_command_line(argn, args, desc, po::command_line_style::unix_style ^ po::command_line_style::allow_short), vm);
1555 po::notify(vm);
1556 //Check if help was prompted
1557 if( vm.count("help") ) {
1558 //Display options
1559 cout << desc << endl;
1560 return false;
1561 }
1562 //Check if coordinates have been input and make sure there's only 3 coordinates
1563 const size_t _size = 3;
1564 if( !vm["coordinates"].empty() && vm["coordinates"].as< std::vector<Real> >().size() == _size ) {
1565 //Save input into coordinates vector (later on the values are stored into a *Real pointer
1566 std::vector<Real> _coordinates = vm["coordinates"].as< std::vector<Real> >();
1567 for( uint i = 0; i < 3; ++i ) {
1568 coordinates[i] = _coordinates[i];
1569 }
1570 //Let the program know we want to get the cell id from coordinates
1571 getCellIdFromCoordinates = true;
1572 }
1573 if( !vm["point1"].empty() && vm["point1"].as< std::vector<Real> >().size() == _size
1574 && !vm["point2"].empty() && vm["point2"].as< std::vector<Real> >().size() == _size ) {
1575 //Save input into point vector (later on the values are stored into a *Real pointer
1576 std::vector<Real> _point1 = vm["point1"].as< std::vector<Real> >();
1577 std::vector<Real> _point2 = vm["point2"].as< std::vector<Real> >();
1578 //Input the values
1579 for( uint i = 0; i < 3; ++i ) {
1580 point1[i] = _point1[i];
1581 point2[i] = _point2[i];
1582 }
1583 _point1.clear();
1584 _point2.clear();
1585 //Check if the user wants to specify number of coordinates we want to calculate:
1586 if( vm.count("pointAmount") ) {
1587 //User specified the number of points -- set it
1588 numberOfCoordinatesInALine = vm["pointAmount"].as<uint32_t>();
1589 }
1590 //Let the program know we want to get the cell id from coordinates
1591 getCellIdFromLine = true;
1592 }
1593 //Check for rotation
1594 if( vm.count("rotate") ) {
1595 //Rotate the vectors (used in convertVelocityBlocks2 as an argument)
1596 rotateVectors = true;
1597 }
1598 if (vm.count("debug") ) {
1599 // Turn on debugging mode
1600 runDebug = true;
1601 }
1602 //Check for plasma frame shifting
1603 if( vm.count("plasmaFrame") ) {
1604 // Shift the velocity distribution to plasma frame
1605 plasmaFrame = true;
1606 }
1607 //Check for cell id input
1608 if( vm.count("cellid") ) {
1609 //Save input
1610 const uint64_t cellId = vm["cellid"].as<uint64_t>();
1611 cellIdList.push_back(cellId);
1612 getCellIdFromInput = true;
1613 }
1614 if( vm.count("cellidlist") ) {
1615 cellIdList = vm["cellidlist"].as< std::vector<uint64_t> >();
1616 getCellIdFromInput = true;
1617 }
1618 if( vm.count("outputdirectory") ) {
1619 //Save input
1620 outputDirectoryPath = vm["outputdirectory"].as< std::vector<string> >();
1621 //Make sure the vector is of length 1:
1622 if( outputDirectoryPath.size() != 1 ) {
1623 return false;
1624 }
1625 //If '/' or '\' was not added to the end of the path, add it:
1626 string & pathName = outputDirectoryPath.back();
1627 //Find the last index of a char with '\' or '/'
1628 const unsigned index = pathName.find_last_of("/\\");
1629 //Check if the last index is '/' or '\':
1630 if( index != (pathName.length() - 1) ) {
1631 //Make sure both '/' and '\' were not used:
1632 const size_t index1 = pathName.find("/");
1633 const size_t index2 = pathName.find("\\");
1634 //Check if the character was found:
1635 if( index1 != string::npos && index2 != string::npos ) {
1636 cout << "Do not use both '/' and '\\' in directory path! " << index1 << " " << index2 << endl;
1637 cout << desc << endl;
1638 return false;
1639 } else if( index1 != string::npos ) {
1640 //The user used '/' in the path
1641 const char c = '/';
1642 //Add '/' at the end
1643 pathName.append( 1, c );
1644 } else {
1645 //The user used '/' in the path
1646 const char c = '\\';
1647 //Add '\' at the end
1648 pathName.append( 1, c );
1649 }
1650 }
1651 } else {
1652 string defaultPath = "";
1653 outputDirectoryPath.push_back(defaultPath);
1654 }
1655 //Declare unit conversion variable (the variable which will multiply coordinates -- by default 1)
1656 Real unit_conversion = 1;
1657 if( vm.count("unit") ) {
1658 //Get the input into 'unit'
1659 const string unit = vm["unit"].as<string>();
1660 if( unit.compare( "re" ) == 0 ) {
1661 //earth radius
1662 unit_conversion = 6371000;
1663 } else if( unit.compare( "km" ) == 0 ) {
1664 //km
1665 unit_conversion = 1000;
1666 } else if( unit.compare( "m" ) == 0 ) {
1667 //meters
1668 unit_conversion = 1;
1669 } else {
1670 //No known unit
1671 cout << "Invalid unit!" << endl;
1672 cout << desc << endl;
1673 return false;
1674 }
1675 //Convert the coordinates into correct units:
1676//getCellIdFromLine, getCellIdFromCoordinates,
1677 if( getCellIdFromLine ) {
1678 const uint16_t vectorSize = 3;
1679 for( uint i = 0; i < vectorSize; ++i ) {
1680 //Multiply the coordinates:
1681 point1[i] = point1[i] * unit_conversion;
1682 point2[i] = point2[i] * unit_conversion;
1683 }
1684 } else if( getCellIdFromCoordinates ) {
1685 const uint16_t vectorSize = 3;
1686 for( uint i = 0; i < vectorSize; ++i ) {
1687 //Multiply the coordinates:
1688 coordinates[i] = coordinates[i] * unit_conversion;
1689 }
1690 } else {
1691 cout << "Nothing to convert!" << endl;
1692 cout << desc << endl;
1693 return false;
1694 }
1695 }
1696
1697 //Make sure the input is correct:
1698 //The cell id can be either received from input or calculated from coordinates or from a line, but only one option is ok:
1699 //Also, we have to get the cell id from somewhere so either cell id must be input or coordinates/line must be input
1700 int count = 0;
1701 if( getCellIdFromLine ) ++count;
1702 if( getCellIdFromInput ) ++count;
1703 if( getCellIdFromCoordinates ) ++count;
1704 if( count != 1 ) {
1705 //Wrong number of arguments
1706 cout << "Contradiction in the way of retrieving cell id ( can only be 1 out of 3 options )" << endl;
1707 return false;
1708 }
1709 } catch( exception &e ) {
1710 cerr << "Error " << e.what() << " at " << __FILE__ << " " << __LINE__ << endl;
1711 return false;
1712 } catch( ... ) {
1713 cerr << "Unknown error" << " at " << __FILE__ << " " << __LINE__ << endl;
1714 return false;
1715 }
1716 //Check to make sure the input for outputDirectoryPath is valid
1717 if( outputDirectoryPath.size() != 1 ) {
1718 cerr << "Error at: " << __FILE__ << " " << __LINE__ << ", invalid outputDirectoryPath!" << endl;
1719 exit(1);
1720 }
1721 //Everything ok
1722 return true;
1723}
1724
1725//Outputs a number of coordinates along a line whose starting point is start and ending point end into outPutCoordinates
1726//Input:
1727//[0] array<Real, 3> & start -- Starting x, y, z coordinates of a line
1728//[1] array<Real, 3> & end -- Starting x, y, z coordinates of a line
1729//[2] unsigned int numberOfCoordinates -- Number of coordinates stored into outputCoordinates
1730//Output:
1731//[0] vector< array<Real, 3> > & outputCoordinates -- Stores the coordinates here
1732//Example: setCoordinatesAlongALine( {0,0,0}, {3,0,0}, 4, output ) would store coordinates {0,0,0}, {1,0,0}, {2,0,0}, {3,0,0} in
1733//output
1735 const CellStructure & cellStruct,
1736 const std::array<Real, 3> & start, const std::array<Real, 3> & end, uint32_t numberOfCoordinates,
1737 std::vector< std::array<Real, 3> > & outputCoordinates
1738 ) {
1739 //Used in calculations in place of numberOfCoordinates
1740 uint32_t _numberOfCoordinates;
1741 //make sure the input is valid
1742 if( numberOfCoordinates == 0 ) {
1743 //Default value -- determine the number of coordinates yourself (Should be about the same size as the number of cells along
1744 //the line
1745 //Calculate the length of the line:
1746 const Real line_length = sqrt(
1747 (end[0] - start[0]) * (end[0] - start[0])
1748 + (end[1] - start[1]) * (end[1] - start[1])
1749 + (end[2] - start[2]) * (end[2] - start[2])
1750 );
1751 Real minCellLength = numeric_limits<Real>::max();
1752
1753 const uint32_t sizeOfCellLength = 3;
1754 //Get the smallest cell length (usually they're all the same size)
1755 for( uint i = 0; i < sizeOfCellLength; ++i ) {
1756 if( minCellLength > cellStruct.cell_length[i] ) {minCellLength = cellStruct.cell_length[i];}
1757 }
1758
1759 if( minCellLength == 0 ) {
1760 cerr << "ERROR, BAD MINIMUM CELL LENGTH AT " << __FILE__ << " " << __LINE__ << endl;
1761 exit(1);
1762 }
1763 _numberOfCoordinates = (uint32_t)( line_length / minCellLength );
1764
1765 //Make sure the number is valid (Must be at least 2 points):
1766 if( _numberOfCoordinates < 2 ) {
1767 cerr << "Cannot use numberOfCoordinates lower than 2 at " << __FILE__ << " " << __LINE__ << endl;
1768 exit(1);
1769 }
1770
1771 //Just to make sure that there's enough coordinates let's add a few more:
1772 _numberOfCoordinates = (uint32_t)(1.2 * _numberOfCoordinates);
1773 } else if( numberOfCoordinates < 2 ) {
1774 cerr << "Cannot use numberOfCoordinates lower than 2 at " << __FILE__ << " " << __LINE__ << endl;
1775 exit(1);
1776 } else {
1777 //User defined input
1778 _numberOfCoordinates = numberOfCoordinates;
1779 }
1780 //Store the unit of line vector ( the vector from start to end divided by the numberOfCoordinates ) into line_unit
1781 std::array<Real, 3> line_unit;
1782 for( uint i = 0; i < 3; ++i ) {
1783 line_unit[i] = (end[i] - start[i]) / (Real)(_numberOfCoordinates - 1);
1784 }
1785
1786 //Insert the coordinates:
1787 outputCoordinates.reserve(_numberOfCoordinates);
1788 for( uint j = 0; j < _numberOfCoordinates; ++j ) {
1789 const std::array<Real, 3> input{{start[0] + j * line_unit[0],
1790 start[1] + j * line_unit[1],
1791 start[2] + j * line_unit[2],}};
1792 outputCoordinates.push_back(input);
1793 }
1794
1795 //Make sure the output is not empty
1796 if( outputCoordinates.empty() ) {
1797 cerr << "Error at: " << __FILE__ << " " << __LINE__ << ", Calculated coordinates empty!" << endl;
1798 exit(1);
1799 }
1800 return;
1801}
1802
1803
1804template <class T>
1805void extractDistribution( const string & fileName, const UserOptions & mainOptions ) {
1806 T vlsvReader;
1807 // Open VLSV file and read mesh names:
1808 vlsvReader.open(fileName);
1809 const string meshName = "SpatialGrid";
1810 const string tagName = "MESH";
1811 const string attributeName = "name";
1812
1813 //Sets cell variables (for cell geometry) -- used in getCellIdFromCoords function
1814 CellStructure cellStruct;
1815 setSpatialCellVariables( vlsvReader, cellStruct );
1816
1817 //Declare a vector for holding multiple cell ids (Note: Used only if we want to calculate the cell id along a line)
1818 std::vector<uint64_t> cellIdList;
1819
1820 //Determine how to get the cell id:
1821 //(getCellIdFromCoords might as well take a vector parameter but since I have not seen many vectors used, I'm keeping to
1822 //previously used syntax)
1823 if( mainOptions.getCellIdFromCoordinates ) {
1824
1825 //Get the cell id list of cell ids with velocity distribution
1826 unordered_set<uint64_t> cellIdList_velocity;
1827 createCellIdList( vlsvReader, cellIdList_velocity );
1828
1829 //Get the cell id from coordinates
1830 //Note: By the way, this is not the same as bool getCellIdFromCoordinates (should change the name)
1831 const uint64_t cellID = getCellIdFromCoords( cellStruct, cellIdList_velocity, mainOptions.coordinates );
1832
1833 if( cellID == numeric_limits<uint64_t>::max() ) {
1834 //Could not find a cell id
1835 cout << "Could not find a cell id in the given coordinates!" << endl;
1836 vlsvReader.close();
1837 return;
1838 }
1839
1840 //Print the cell id:
1841 //store the cel lid in the list of cell ids (This is only used because it makes the code for
1842 //calculating the cell ids from a line clearer)
1843 cellIdList.push_back( cellID );
1844 } else if( mainOptions.getCellIdFromLine ) {
1845 //Get the cell id list of cell ids with velocity distribution
1846 unordered_set<uint64_t> cellIdList_velocity;
1847 createCellIdList( vlsvReader, cellIdList_velocity );
1848
1849 //Now there are multiple cell ids so do the same treatment for the cell ids as with getCellIdFromCoordinates
1850 //but now for multiple cell ids
1851
1852 //Declare a vector for storing coordinates:
1853 std::vector< std::array<Real, 3> > coordinateList;
1854 //Store cell ids into coordinateList:
1855 //Note: All mainOptions are user-input
1856 setCoordinatesAlongALine( cellStruct, mainOptions.point1, mainOptions.point2, mainOptions.numberOfCoordinatesInALine, coordinateList );
1857 //Note: (getCellIdFromCoords might as well take a vector parameter but since I have not seen many vectors used,
1858 // I'm keeping to previously used syntax)
1859 //Declare an iterator
1860 std::vector< std::array<Real, 3> >::iterator it;
1861 //Calculate every cell id in coordinateList
1862 for( it = coordinateList.begin(); it != coordinateList.end(); ++it ) {
1863 //NOTE: since this code is nearly identical to the code for calculating single coordinates, it could be smart to create a separate function for this
1864 //declare coordinates array
1865 const std::array<Real, 3> & coords = *it;
1866 //Get the cell id from coordinates
1867 const uint64_t cellID = getCellIdFromCoords( cellStruct, cellIdList_velocity, coords );
1868 if( cellID != numeric_limits<uint64_t>::max() ) {
1869 //A valid cell id:
1870 //Store the cell id in the list of cell ids but only if it is not already there:
1871 if( cellIdList.empty() ) {
1872 //cell id list empty so it's safe to input
1873 cellIdList.push_back( cellID );
1874 } else if( cellIdList.back() != cellID ) {
1875 //cellID has not already been added, so add it now:
1876 cellIdList.push_back( cellID );
1877 }
1878 }
1879 }
1880 } else if( mainOptions.getCellIdFromInput ) {
1881 //Declare cellID and set it if the cell id is specified by the user
1882 //bool getCellIdFromLine equals true) -- this is done later on in the code ( After the file has been opened)
1883 for(std::vector<uint64_t>::const_iterator id = mainOptions.cellIdList.begin(); id != mainOptions.cellIdList.end() ; id++) {
1884 //store the cell id in the list of cell ids (This is only used because it makes the code for
1885 //calculating the cell ids from a line clearer)
1886 cellIdList.push_back( *id );
1887 }
1888 } else {
1889 //This should never happen but it's better to be safe than sorry
1890 cerr << "Error at: " << __FILE__ << " " << __LINE__ << ", No user input for cell id retrieval!" << endl;
1891 vlsvReader.close();
1892 exit(1);
1893 }
1894
1895 //Check for proper input
1896 if( cellIdList.empty() ) {
1897 cout << "Could not find a cell id!" << endl;
1898 return;
1899 }
1900
1901 //Next task is to iterate through the cell ids and save files:
1902 //Save all of the cell ids' velocities into files:
1903 std::vector<uint64_t>::iterator it;
1904 //declare extractNum for keeping track of which extraction is going on and informing the user (used in the iteration)
1905 int extractNum = 1;
1906 //Give some info on how many extractions there are and what the save path is:
1907 cout << "Save path: " << mainOptions.outputDirectoryPath.front() << endl;
1908 cout << "Total number of extractions: " << cellIdList.size() << endl;
1909 //Iterate:
1910 for( it = cellIdList.begin(); it != cellIdList.end(); ++it ) {
1911 //get the cell id from the iterator:
1912 const uint64_t cellID = *it;
1913 //Print out the cell id:
1914 cout << "Cell id: " << cellID << endl;
1915 // Create a new file suffix for the output file:
1916 stringstream ss1;
1917 ss1 << ".vlsv";
1918 string newSuffix;
1919 ss1 >> newSuffix;
1920
1921 // Create a new file prefix for the output file:
1922 stringstream ss2;
1923 ss2 << "velgrid" << '.';
1924 if( mainOptions.rotateVectors ) {
1925 ss2 << "rotated" << '.';
1926 }
1927 if( mainOptions.plasmaFrame ) {
1928 ss2 << "shifted" << '.';
1929 }
1930 ss2 << cellID;
1931 string newPrefix;
1932 ss2 >> newPrefix;
1933
1934 // Replace .vlsv with the new suffix:
1935 string outputFileName = fileName;
1936 size_t pos = outputFileName.rfind(".vlsv");
1937 if (pos != string::npos) outputFileName.replace(pos, 5, newSuffix);
1938
1939 pos = outputFileName.find(".");
1940 if (pos != string::npos) outputFileName.replace(0, pos, newPrefix);
1941
1942 string slicePrefix = "VelSlice";
1943 string outputSliceName = fileName;
1944 pos = outputSliceName.find(".");
1945 if (pos != string::npos) outputSliceName.replace(0,pos,slicePrefix);
1946
1947 //Declare the file path (used in DBCreate to save the file in the correct location)
1948 string outputFilePath;
1949 //Get the path (outputDirectoryPath was retrieved from user input and it's a vector<string>):
1950 outputFilePath.append( mainOptions.outputDirectoryPath.front() );
1951 //The complete file path is still missing the file name, so add it to the end:
1952 outputFilePath.append( outputFileName );
1953
1954 // Extract velocity grid from VLSV file, if possible, and write as vlsv file:
1955 bool velGridExtracted = true;
1956 //slice disabled by default, enable for specific testing. TODO: add command line interface for enabling it
1957 //convertSlicedVelocityMesh(vlsvReader,outputSliceName,*it2,cellStruct);
1958 if (convertVelocityBlocks2(vlsvReader, outputFilePath, meshName, cellStruct, cellID, mainOptions.rotateVectors, mainOptions.plasmaFrame ) == false) {
1959 velGridExtracted = false;
1960 } else {
1961 //Display message for the user:
1962 if( mainOptions.getCellIdFromLine ) {
1963 //Extracting multiple cell ids:
1964 //Display how mant extracted and how many more to go:
1965 int moreToGo = cellIdList.size() - extractNum;
1966 //Display message
1967 cout << "Extracted num. " << extractNum << ", " << moreToGo << " more to go" << endl;
1968 //Move to the next extraction number
1969 ++extractNum;
1970 } else {
1971 //Single cell id:
1972 cout << "\t extracted from '" << fileName << "'" << endl;
1973 }
1974 }
1975
1976 // If velocity grid was not extracted, delete the file:
1977 if (velGridExtracted == false) {
1978 cerr << "ERROR, FAILED TO EXTRACT VELOCITY GRID AT: " << __FILE__ << " " << __LINE__ << endl;
1979 if (remove(outputFilePath.c_str()) != 0) {
1980 cerr << "\t ERROR: failed to remote dummy output file!" << endl;
1981 }
1982 }
1983 }
1984
1985 vlsvReader.close();
1986}
1987
1988int main(int argn, char* args[]) {
1989 // Deal with OpenMPI 4.x VLSV write bug
1990 int required=MPI_THREAD_FUNNELED;
1991 int provided, resultlen;
1992 char mpiversion[MPI_MAX_LIBRARY_VERSION_STRING];
1993 bool overrideMCAompio = false;
1994
1995 MPI_Get_library_version(mpiversion, &resultlen);
1996 string versionstr = string(mpiversion);
1997 stringstream mpiioMessage;
1998 if(versionstr.find("Open MPI") != std::string::npos) {
1999 #ifdef VLASIATOR_ALLOW_MCA_OMPIO
2000 mpiioMessage << "We detected OpenMPI but the compilation flag VLASIATOR_ALLOW_MCA_OMPIO was set so we do not override the default MCA io flag." << endl;
2001 #else
2002 overrideMCAompio = true;
2003 int index, count;
2004 char io_value[64];
2005 MPI_T_cvar_handle io_handle;
2006
2007 MPI_T_init_thread(required, &provided);
2008 MPI_T_cvar_get_index("io", &index);
2009 MPI_T_cvar_handle_alloc(index, NULL, &io_handle, &count);
2010 MPI_T_cvar_write(io_handle, "^ompio");
2011 MPI_T_cvar_read(io_handle, io_value);
2012 MPI_T_cvar_handle_free(&io_handle);
2013 mpiioMessage << "We detected OpenMPI so we set the cvars value to disable ompio, MCA io: " << io_value << endl;
2014 #endif
2015 }
2016
2017 int ntasks, rank;
2018 MPI_Init_thread(&argn,&args,required,&provided);
2019 MPI_Comm_size(MPI_COMM_WORLD, &ntasks);
2020 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2021 if (required > provided){
2022 if(rank == 0) {
2023 cerr << "MPI_Init_thread failed! Got " << provided << ", need "<<required <<endl;
2024 }
2025 exit(1);
2026 }
2027 if (rank == 0) {
2028 const char* mpiioenv = std::getenv("OMPI_MCA_io");
2029 if(mpiioenv != nullptr) {
2030 std::string mpiioenvstr(mpiioenv);
2031 if(mpiioenvstr.find("^ompio") == std::string::npos) {
2032 cout << mpiioMessage.str();
2033 }
2034 }
2035 }
2036
2037 //Get the file name
2038 const string mask = args[1];
2039 std::vector<string> fileList = toolutil::getFiles(mask);
2040
2041 //Retrieve options variables:
2042 UserOptions mainOptions;
2043
2044 //Get user input and set the retrieve options variables
2045 if( retrieveOptions( argn, args, mainOptions ) == false ) {
2046 //Failed to retrieve options (Due to contradiction or an error)
2047 printUsageMessage(); //Prints the usage message
2048 return 0;
2049 }
2050 if (rank == 0 && argn < 3) {
2051 //Failed to retrieve options (Due to contradiction or an error)
2052 printUsageMessage(); //Prints the usage message
2053 return 0;
2054 }
2055
2056 //Convert files
2057 int entryCounter = 0;
2058 for (size_t entryName = 0; entryName < fileList.size(); entryName++) {
2059 if (entryCounter++ % ntasks == rank) {
2060 //Get the file name
2061 const string & fileName = fileList[entryName];
2062 extractDistribution<vlsvinterface::Reader>( fileName, mainOptions );
2063 }
2064 }
2065
2066 if(overrideMCAompio) {
2067 MPI_T_finalize();
2068 }
2069 MPI_Finalize();
2070 return 0;
2071}
for i
Definition Dispersion.m:24
set(gca, 'YDir', 'normal')
sqrt(1.0+vA *vA/(c *c))) % Ion-acoustic wave cS
Constants c
Definition Dispersion.m:45
std::vector< std::string > outputDirectoryPath
Definition vlsvextract.h:81
bool rotateVectors
Definition vlsvextract.h:76
bool getCellIdFromLine
Definition vlsvextract.h:73
bool getCellIdFromInput
Definition vlsvextract.h:74
std::array< Real, 3 > point1
Definition vlsvextract.h:83
uint32_t numberOfCoordinatesInALine
Definition vlsvextract.h:80
std::array< Real, 3 > coordinates
Definition vlsvextract.h:82
bool plasmaFrame
Definition vlsvextract.h:77
std::array< Real, 3 > point2
Definition vlsvextract.h:84
std::vector< uint64_t > cellIdList
Definition vlsvextract.h:79
uint64_t cellId
Definition vlsvextract.h:78
bool getCellIdFromCoordinates
Definition vlsvextract.h:75
uint64_t getBlockOffset(const uint64_t &cellId)
bool getBlockIds(const uint64_t &cellId, std::vector< uint64_t > &blockIds, const std::string &popName)
bool setCellsWithBlocks(const std::string &meshName, const std::string &popName)
bool getCellIds(std::vector< uint64_t > &cellIds, const std::string &meshName="SpatialGrid")
bool getVelocityBlockVariables(const std::string &variableName, const uint64_t &cellId, char *&buffer, bool allocateMemory=true)
float Real
Definition definitions.h:41
static creal EPS
Definition fs_common.h:61
const int blockSize
const int j
const int k
const Realf vz_min
#define index(i, j, k)
std::vector< std::string > getFiles(const std::string &mask)
Definition vlsv_util.cpp:36
uint64_t vcell_bounds[3]
Definition vlsv2silo.cpp:52
Real min_vcoordinates[3]
Definition vlsv2silo.cpp:56
uint32_t maxVelRefLevel
Definition vlsvextract.h:47
Real vblock_length[3]
Definition vlsv2silo.cpp:54
uint64_t cell_bounds[3]
Definition vlsv2silo.cpp:45
int slicedCoords[3]
Definition vlsvextract.h:49
Real min_coordinates[3]
Definition vlsv2silo.cpp:49
Real slicedCoordValues[3]
Definition vlsvextract.h:50
Real cell_length[3]
Definition vlsv2silo.cpp:47
bool operator()(const NodeCrd< double > &a, const NodeCrd< double > &b) const
int main()
static ARCH_HOSTDEV VecSimple< T > floor(VecSimple< T > const &a)
static map< string, string > attributes
Definition vlsvdiff.cpp:71
bool createCellIdList(T &vlsvReader, unordered_set< uint64_t > &cellIdList)
static bool runDebug
bool setVelocityMeshVariables(vlsv::Reader &vlsvReader, CellStructure &cellStruct)
void applyRotation(const Real *B, Real *transform)
void setCoordinatesAlongALine(const CellStructure &cellStruct, const std::array< Real, 3 > &start, const std::array< Real, 3 > &end, uint32_t numberOfCoordinates, std::vector< std::array< Real, 3 > > &outputCoordinates)
void getCellCoordinates(const CellStructure &cellStruct, const uint64_t cellId, Real *coordinates)
void extractDistribution(const string &fileName, const UserOptions &mainOptions)
void getB(Real *B, vlsvinterface::Reader &vlsvReader, const string &meshName, const uint64_t &cellID)
bool convertSlicedVelocityMesh(vlsvinterface::Reader &vlsvReader, const string &fname, const string &meshName, CellStructure &cellStruct, const std::string &popName)
uint64_t convUInt(const char *ptr, const datatype::type &dataType, const uint64_t &dataSize)
uint64_t searchForBestCellId(const CellStructure &cellStruct, const uint64_t *cellIdList, const Real *coordinates, const uint64_t sizeOfCellIdList)
uint64_t getCellIdFromCoords(const CellStructure &cellStruct, const unordered_set< uint64_t > cellIdList, const std::array< Real, 3 > coords)
void printUsageMessage()
bool convertVelocityBlocks2(vlsvinterface::Reader &vlsvReader, const string &fname, const string &meshName, CellStructure &cellStruct, const uint64_t &cellID, const bool rotate, const bool plasmaFrame, vlsv::Writer &out, const std::string &popName)
bool retrieveOptions(const int argn, char *args[], UserOptions &mainOptions)
void applyTranslation(const Real *V_bulk, Real *transform)
bool setSpatialCellVariables(Reader &vlsvReader, CellStructure &cellStruct)
void getBulkVelocity(Real *V_bulk, vlsvinterface::Reader &vlsvReader, const string &meshName, const string &popName, const uint64_t &cellID)