Nektar++
VtkToFld.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: VtkToFld.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description:
32//
33///////////////////////////////////////////////////////////////////////////////
34
36#include <vtkPolyDataReader.h>
37
38#if VTK_MAJOR_VERSION >= 9
39#include <limits>
40#include <stdexcept>
41#endif
42
43#include <vtkCellArray.h>
44#include <vtkCellDataToPointData.h>
45#include <vtkContourFilter.h>
46#include <vtkPointData.h>
47#include <vtkPoints.h>
48#include <vtkPolyData.h>
49
50#include <boost/program_options.hpp>
51namespace po = boost::program_options;
52
60
61using namespace std;
62using namespace Nektar;
63
64/**
65 * @brief Represents a vertex in the mesh.
66 *
67 * Each vertex has a 3-component coordinate and a scalar value associated with
68 * it. The factor provides a mechanism to specify precision of the coordinate
69 * comparison. Although coordinates are provided as floating-point numbers, they
70 * are stored as integers. The integer value is computed as
71 * floor (x * factor)
72 * Therefore a factor of 100 would ensure a precision of 0.01 in the comparison.
73 */
74struct Vertex
75{
76 Vertex(double pX, double pY, double pZ, double pScalar, double factor)
77 : x((int)floor(pX * factor)), y((int)floor(pY * factor)),
78 z((int)floor(pZ * factor)), scalar(pScalar)
79 {
80 }
81
82 int x;
83 int y;
84 int z;
85 double scalar;
86
87 bool operator==(const Vertex &v)
88 {
89 return (x == v.x && y == v.y && z == v.z);
90 }
91};
92typedef std::shared_ptr<Vertex> VertexSharedPtr;
93
94/// Define comparison operator for the vertex struct
95bool operator==(const VertexSharedPtr &v1, const VertexSharedPtr &v2)
96{
97 return v1->operator==(*v2);
98}
99
100/**
101 * @brief Hash function for the Vertex struct used for defining sets.
102 */
104{
105 std::size_t operator()(VertexSharedPtr const &p) const
106 {
107 return hash_combine(p->x, p->y, p->z);
108 }
109};
110
111/// Define a set of Vertices with associated hash function
112typedef std::unordered_set<VertexSharedPtr, VertexHash> VertexSet;
113
114/**
115 * Main function.
116 *
117 * Usage: VtkToFld session.xml input.vtk output.fld [options]
118 */
119int main(int argc, char *argv[])
120{
121 // Set up available options
122 po::options_description desc("Available options");
123
124 // clang-format off
125 desc.add_options()
126 ("help,h", "Produce this help message.")
127 ("name,n", po::value<string>()->default_value("Intensity"),
128 "Name of field in VTK file to use for intensity.")
129 ("outname,m", po::value<string>()->default_value("intensity"),
130 "Name of field in output FLD file.")
131 ("precision,p", po::value<double>()->default_value(1),
132 "Precision of vertex matching.");
133 // clang-format on
134
135 po::options_description hidden("Hidden options");
136
137 // clang-format off
138 hidden.add_options()
139 ("file", po::value<vector<string> >(), "Input filename");
140 // clang-format on
141
142 po::options_description cmdline_options;
143 cmdline_options.add(desc).add(hidden);
144
145 po::positional_options_description p;
146 p.add("file", -1);
147
148 po::variables_map vm;
149
150 // Parse command-line options
151 try
152 {
153 po::store(po::command_line_parser(argc, argv)
154 .options(cmdline_options)
155 .positional(p)
156 .run(),
157 vm);
158 po::notify(vm);
159 }
160 catch (const std::exception &e)
161 {
162 cerr << e.what() << endl;
163 cerr << desc;
164 return 1;
165 }
166
167 if (vm.count("help") || vm.count("file") == 0 ||
168 vm["file"].as<vector<string>>().size() != 3)
169 {
170 cerr << "Usage: VtkToFld session.xml intensity.vtk output.fld [options]"
171 << endl;
172 cerr << desc;
173 return 1;
174 }
175
176 // Extract command-line argument values
177 std::vector<std::string> vFiles = vm["file"].as<vector<string>>();
178 const string infile = vFiles[1];
179 const string outfile = vFiles[2];
180 const double factor = vm["precision"].as<double>();
181 const string name = vm["name"].as<string>();
182 const string outname = vm["outname"].as<string>();
183
184 std::vector<std::string> vFilenames;
188
189 vFilenames.push_back(vFiles[0]);
190 vSession = LibUtilities::SessionReader::CreateInstance(2, argv, vFilenames);
191
192 try
193 {
194 //----------------------------------------------
195 // Read in mesh from input file
196 graph2D = SpatialDomains::MeshGraphIO::Read(vSession);
197 //----------------------------------------------
198
199 //----------------------------------------------
200 // Define Expansion
202 graph2D);
203 //----------------------------------------------
204
205 //----------------------------------------------
206 // Set up coordinates of mesh
207 int coordim = Exp->GetCoordim(0);
208 int nq = Exp->GetNpoints();
209
210 Array<OneD, NekDouble> xc0(nq, 0.0);
211 Array<OneD, NekDouble> xc1(nq, 0.0);
212 Array<OneD, NekDouble> xc2(nq, 0.0);
213
214 switch (coordim)
215 {
216 case 2:
217 Exp->GetCoords(xc0, xc1);
218 break;
219 case 3:
220 Exp->GetCoords(xc0, xc1, xc2);
221 break;
222 default:
223 ASSERTL0(false, "Coordim not valid");
224 break;
225 }
226 //----------------------------------------------
227
228 vtkPolyDataReader *vtkMeshReader = vtkPolyDataReader::New();
229 vtkMeshReader->SetFileName(infile.c_str());
230 vtkMeshReader->Update();
231
232 vtkPolyData *vtkMesh = vtkMeshReader->GetOutput();
233 vtkCellDataToPointData *c2p = vtkCellDataToPointData::New();
234#if VTK_MAJOR_VERSION <= 5
235 c2p->SetInput(vtkMesh);
236#else
237 c2p->SetInputData(vtkMesh);
238#endif
239 c2p->PassCellDataOn();
240 c2p->Update();
241 vtkPolyData *vtkDataAtPoints = c2p->GetPolyDataOutput();
242
243 vtkPoints *vtkPoints = vtkMesh->GetPoints();
244 ASSERTL0(vtkPoints, "ERROR: cannot get points from mesh.");
245
246 vtkCellArray *vtkPolys = vtkMesh->GetPolys();
247 ASSERTL0(vtkPolys, "ERROR: cannot get polygons from mesh.");
248
249 vtkPointData *vtkPData = vtkDataAtPoints->GetPointData();
250 ASSERTL0(vtkPolys, "ERROR: cannot get point data from file.");
251
252 VertexSet points;
253 VertexSet::iterator vIter;
254 double p[3];
255 double val;
256 double x, y, z;
257 int coeff_idx;
258 int i, j, n;
259
260 if (!vtkDataAtPoints->GetPointData()->HasArray(name.c_str()))
261 {
262 n = vtkDataAtPoints->GetPointData()->GetNumberOfArrays();
263 cerr << "Input file '" << infile
264 << "' does not have a field named '" << name << "'" << endl;
265 cerr << "There are " << n << " arrays in this file." << endl;
266 for (int i = 0; i < n; ++i)
267 {
268 cerr << " "
269 << vtkDataAtPoints->GetPointData()->GetArray(i)->GetName()
270 << endl;
271 }
272 return 1;
273 }
274
275 // Build up an unordered set of vertices from the VTK file. For each
276 // vertex a hashed value of the coordinates is generated to within a
277 // given tolerance.
278 n = vtkPoints->GetNumberOfPoints();
279 for (i = 0; i < n; ++i)
280 {
281 vtkPoints->GetPoint(i, p);
282 val = vtkPData->GetScalars(name.c_str())->GetTuple1(i);
283 std::shared_ptr<Vertex> v(
284 new Vertex(p[0], p[1], p[2], val, factor));
285 points.insert(v);
286 }
287
288 // Now process each vertex of each element in the mesh
290 for (i = 0; i < Exp->GetNumElmts(); ++i)
291 {
292 StdRegions::StdExpansionSharedPtr e = Exp->GetExp(i);
293 for (j = 0; j < e->GetNverts(); ++j)
294 {
295 // Get the index of the coefficient corresponding to this vertex
296 coeff_idx = Exp->GetCoeff_Offset(i) + e->GetVertexMap(j);
297
298 // Get the coordinates of the vertex
299 vert =
300 e->as<LocalRegions::Expansion2D>()->GetGeom2D()->GetVertex(
301 j);
302 vert->GetCoords(x, y, z);
303
304 // Look up the vertex in the VertexSet
305 std::shared_ptr<Vertex> v(new Vertex(x, y, z, 0.0, factor));
306 vIter = points.find(v);
307
308 // If not found, maybe the tolerance should be reduced?
309 // If found, record the scalar value from the VTK file in the
310 // corresponding coefficient.
311 if (vIter == points.end())
312 {
313 cerr << "Vertex " << i << " not found. Looking for (" << x
314 << ", " << y << ", " << z << ")" << endl;
315 }
316 else
317 {
318 Exp->UpdateCoeffs()[coeff_idx] = (*vIter)->scalar;
319 }
320 }
321 }
322 Exp->SetPhysState(false);
323
324 //-----------------------------------------------
325 // Write solution to file
326 std::vector<LibUtilities::FieldDefinitionsSharedPtr> FieldDef =
327 Exp->GetFieldDefinitions();
328 std::vector<std::vector<NekDouble>> FieldData(FieldDef.size());
329
330 for (i = 0; i < FieldDef.size(); ++i)
331 {
332 FieldDef[i]->m_fields.push_back(outname);
333 Exp->AppendFieldData(FieldDef[i], FieldData[i]);
334 }
335
337 LibUtilities::FieldIO::CreateDefault(vSession);
338 vFld->Write(outfile, FieldDef, FieldData);
339 //-----------------------------------------------
340 }
341 catch (...)
342 {
343 cout << "An error occurred." << endl;
344 }
345}
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
int main(int argc, char *argv[])
Definition: VtkToFld.cpp:119
bool operator==(const VertexSharedPtr &v1, const VertexSharedPtr &v2)
Define comparison operator for the vertex struct.
Definition: VtkToFld.cpp:95
std::unordered_set< VertexSharedPtr, VertexHash > VertexSet
Define a set of Vertices with associated hash function.
Definition: VtkToFld.cpp:112
std::shared_ptr< Vertex > VertexSharedPtr
Definition: VtkToFld.cpp:92
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
void GetCoords(Array< OneD, NekDouble > &coords_1, Array< OneD, NekDouble > &coords_2=NullNekDouble1DArray, Array< OneD, NekDouble > &coords_3=NullNekDouble1DArray)
this function returns the physical coordinates of the quadrature points of the expansion
Definition: StdExpansion.h:579
std::shared_ptr< FieldIO > FieldIOSharedPtr
Definition: FieldIO.h:322
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:174
std::shared_ptr< PointGeom > PointGeomSharedPtr
Definition: Geometry.h:57
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
std::vector< double > z(NPUPPER)
void hash_combine(std::size_t &seed)
Definition: HashUtils.hpp:44
STL namespace.
Hash function for the Vertex struct used for defining sets.
Definition: VtkToFld.cpp:104
std::size_t operator()(VertexSharedPtr const &p) const
Definition: VtkToFld.cpp:105
Represents a vertex in the mesh.
Definition: VtkToFld.cpp:75
Vertex(double pX, double pY, double pZ, double pScalar, double factor)
Definition: VtkToFld.cpp:76
int y
Definition: VtkToFld.cpp:83
int z
Definition: VtkToFld.cpp:84
bool operator==(const Vertex &v)
Definition: VtkToFld.cpp:87
double scalar
Definition: VtkToFld.cpp:85
int x
Definition: VtkToFld.cpp:82