OpenLB 1.7
Loading...
Searching...
No Matches
analyticalVelocityVolumeF.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2023 Adrian Kummerländer, Dennis Teutscher, Shota Ito
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (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
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24#ifndef ANALYTICAL_VELOCITY_VOLUME_F_H
25#define ANALYTICAL_VELOCITY_VOLUME_F_H
26
27#if defined(FEATURE_VTK)
28#include <vtkSmartPointer.h>
29#include <vtkImageData.h>
30#include <vtkXMLImageDataReader.h>
31#include <vtkPointData.h>
32#include <vtkCellData.h>
33#include <vtkDataArray.h>
34#include <vtkCellLocator.h>
35#endif
36
37namespace olb {
38template <typename T>
39class AnalyticalVelocityVolumeF final : public AnalyticalF<3,T,T> {
40private:
41#if defined(FEATURE_VTK)
42 vtkSmartPointer<vtkXMLImageDataReader> _reader = vtkSmartPointer<vtkXMLImageDataReader>::New();
43 vtkSmartPointer<vtkImageData> _data;
44 vtkSmartPointer<vtkCellLocator> _cellLocator = vtkSmartPointer<vtkCellLocator>::New();
45#endif
46
47 std::string _fileName;
48 Vector<double,3> _origin{};
49 Vector<int,3> _shape{};
50 T _spacing = 0.0;
51
52 bool CellData = false;
53 bool PointData = false;
54
55public:
56 AnalyticalVelocityVolumeF(std::string fileName)
57 : AnalyticalF<3,T,T>(3)
58 {
59 this->getName() = "VelocityVolumeImporter";
60
61 OstreamManager clout(std::cout, "VelocityVolumeImporter");
62 _fileName = fileName;
63
64 #if not defined(FEATURE_VTK)
65 if (isVTIFile(_fileName))
66 {
67 std::cerr << "To use the VTK format, add VTK to the FEATURES list in config.mk";
68 exit(1);
69 }
70 #endif
71 #if defined(FEATURE_VTK)
72 if (!isVTIFile(_fileName)) {
73 std::cerr << "Please convert your file to .vti to use the functor.";
74 exit(1);
75 } else {
76 clout << "Read .vti file..." << std::endl;
77 _reader->SetFileName(fileName.c_str());
78 _reader->Update();
79 auto* _data = _reader->GetOutput();
80
81 _spacing = static_cast<T>(_data->GetSpacing()[0]);
82 clout << "Read spacing : " << _spacing << std::endl;
83 _data->GetDimensions(_shape.data());
84 clout << "Read shape : " << _shape << std::endl;
85 _data->GetOrigin(_origin.data());
86 clout << "Read origin : " << _origin << std::endl;
87
88 vtkCellData* _cellData = _data->GetCellData();
89 vtkPointData* _pointData = _data->GetPointData();
90 if (_cellData->GetNumberOfArrays() > 0) {
91 clout << "Found CellData. " << std::endl;
92 CellData = true;
93 _cellLocator->SetDataSet(_data);
94 _cellLocator->BuildLocator();
95 } else if (_pointData->GetNumberOfArrays() > 0) {
96 clout << "Found PointData." << std::endl;
97 clout << "Warning: If functor reads only 0, consider converting PointData to CellData." << std::endl;
98 PointData = true;
99 } else {
100 std::cerr << "Neither cell data nor point data found.";
101 exit(1);
102 }
103 }
104 #endif
105 }
106
108 return _shape * _spacing;
109 }
110
111 T getSpacing() const {
112 return _spacing;
113 }
114
115 bool operator()(T output[], const T physR[]) override{
116 #if defined(FEATURE_VTK)
117 if (!isInside(physR)) {
118 //std::cout << "Point outside." << std::endl;
119 output[0] = 0;
120 output[1] = 0;
121 output[2] = 0;
122 return true;
123 }
124
125 auto* _data = _reader->GetOutput();
126
127 // cell data (preferred)
128 if (CellData) {
129 vtkCellData* _cellData = _data->GetCellData();
130 // Assuming cellData holds the velocity data in the first array
131 vtkDataArray* _vectors = _cellData->GetVectors(_cellData->GetArrayName(0));
132 if (_vectors == nullptr) {
133 std::cerr << "[AnalyticalVelocityVolumeF]: ";
134 std::cerr << "Cell data: No vector data was found." << std::endl;
135 exit(1);
136 }
137
138 double x[3] = {physR[0], physR[1], physR[2]};
139 vtkIdType cellId = _cellLocator->FindCell(x);
140 if (cellId >= 0) {
141 double velocity[3] = {};
142 _vectors->GetTuple(cellId, velocity);
143 for (int dim = 0; dim < 3; ++dim) {
144 output[dim] = static_cast<T>(velocity[dim]);
145 }
146 } else {
147 //std::cout << "Cell not found." << std::endl;
148 output[0] = 0;
149 output[1] = 0;
150 output[2] = 0;
151 }
152 }
153
154 // point data (can cause problems due to round-off)
155 else if (PointData) {
156 vtkPointData* _pointData = _data->GetPointData();
157 // Assuming pointData holds the velocity data in the first array
158 vtkDataArray* _vectors = _pointData->GetVectors(_pointData->GetArrayName(0));
159 if (_vectors == nullptr) {
160 std::cerr << "[AnalyticalVelocityVolumeF]: ";
161 std::cerr << "Point data: No vector data was found." << std::endl;
162 return false;
163 }
164
165 Vector<int,3> x = getVtiLatticeR(physR);
166 vtkIdType pointId = _data->FindPoint(x[0], x[1], x[2]);
167 if (pointId >= 0) {
168 double velocity[3] = {};
169 _vectors->GetTuple(pointId, velocity);
170 for (int dim = 0; dim < 3; ++dim) {
171 output[dim] = static_cast<T>(velocity[dim]);
172 }
173 } else {
174 //std::cout << "Point not found." << std::endl;
175 output[0] = 0;
176 output[1] = 0;
177 output[2] = 0;
178 }
179 }
180 #endif
181 return true;
182 }
183
184private:
185 bool isVTIFile(const std::string& fileName) {
186 return (fileName.size() >= 4 && fileName.substr(fileName.size() - 4) == ".vti");
187 }
188
189 Vector<int,3> getVtiLatticeR(const T physR[]) {
190 int iX;
191 int iY;
192 int iZ;
193 iX = util::floor(physR[0] / _spacing);
194 iY = util::floor(physR[1] / _spacing);
195 iZ = util::floor(physR[2] / _spacing);
196 return {iX, iY, iZ};
197 }
198
199 bool isInside(const T physR[]) {
200 Vector<int,3> vtiLatticeR = getVtiLatticeR(physR);
201 int iX = vtiLatticeR[0];
202 int iY = vtiLatticeR[1];
203 int iZ = vtiLatticeR[2];
204 return (iX >= 0 && iY >= 0 && iZ >= 0 && iX < _shape[0] && iY < _shape[1] && iZ < _shape[2]);
205 }
206};
207}
208
209#endif
AnalyticalF are applications from DD to XD, where X is set by the constructor.
static constexpr unsigned dim
bool operator()(T output[], const T physR[]) override
AnalyticalVelocityVolumeF(std::string fileName)
std::string & getName()
read and write access to name
Definition genericF.hh:51
class for marking output with some text
Plain old scalar vector.
Definition vector.h:47
constexpr const T * data() const any_platform
Definition vector.h:161
ADf< T, DIM > floor(const ADf< T, DIM > &a)
Definition aDiff.h:869
Top level namespace for all of OpenLB.