Bembel
 
Loading...
Searching...
No Matches
VTKSurfaceExport.hpp
1// This file is part of Bembel, the higher order C++ boundary element library.
2//
3// Copyright (C) 2022 see <http://www.bembel.eu>
4//
5// It was written as part of a cooperation of J. Doelz, H. Harbrecht, S. Kurz,
6// M. Multerer, S. Schoeps, and F. Wolf at Technische Universitaet Darmstadt,
7// Universitaet Basel, and Universita della Svizzera italiana, Lugano. This
8// source code is subject to the GNU General Public License version 3 and
9// provided WITHOUT ANY WARRANTY, see <http://www.bembel.eu> for further
10// information.
11
12#ifndef BEMBEL_SRC_IO_VTKSURFACEEXPORT_HPP_
13#define BEMBEL_SRC_IO_VTKSURFACEEXPORT_HPP_
14
15namespace Bembel {
16
25 public:
32 init_VTKSurfaceExport(geo, M);
33 }
34 inline void init_VTKSurfaceExport(const Geometry& geo, int M) {
36 points = msh.get_element_tree().generatePointList().transpose();
37 cells = msh.get_element_tree().generateElementList().transpose();
38 normals = Eigen::MatrixXd(cells.rows(), 3);
39 patch_number = Eigen::VectorXi(cells.rows());
40
41 for (auto e = msh.get_element_tree().cpbegin();
42 e != msh.get_element_tree().cpend(); ++e) {
43 normals.row(e->id_) = msh.get_geometry()[e->patch_]
44 .evalNormal(e->referenceMidpoint())
45 .normalized()
46 .transpose();
47 }
48 for (auto e = msh.get_element_tree().cpbegin();
49 e != msh.get_element_tree().cpend(); ++e) {
50 patch_number(e->id_) = e->patch_;
51 }
52 return;
53 }
57 inline void addDataSet(
58 const std::string& name,
59 std::function<double(int, const Eigen::Vector2d&)> fun) {
60 addDataSet_(name, getData_<double>(fun));
61 return;
62 }
66 inline void addDataSet(
67 const std::string& name,
68 std::function<std::complex<double>(int, const Eigen::Vector2d&)> fun) {
69 Eigen::VectorXcd data = getData_<std::complex<double>>(fun);
70 addDataSet_(name + std::string("_real"), data.real());
71 addDataSet_(name + std::string("_imag"), data.imag());
72 return;
73 }
77 inline void addDataSet(
78 const std::string& name,
79 std::function<Eigen::Vector3d(int, const Eigen::Vector2d&)> fun) {
80 addDataSet_(name, getData_<double, 3>(fun));
81 return;
82 }
86 inline void addDataSet(
87 const std::string& name,
88 std::function<Eigen::Vector3cd(int, const Eigen::Vector2d&)> fun) {
89 Eigen::MatrixXcd data = getData_<std::complex<double>, 3>(fun);
90 addDataSet_(name + std::string("_real"), data.real());
91 addDataSet_(name + std::string("_imag"), data.imag());
92 return;
93 }
97 inline void addDataSet(
98 const std::string& name,
99 std::function<Eigen::Vector3d(const Eigen::Vector3d&)> fun) {
100 addDataSet_(name, getData_<double, 3>(fun));
101 return;
102 }
106 inline void addDataSet(
107 const std::string& name,
108 std::function<Eigen::Vector3cd(const Eigen::Vector3d&)> fun) {
109 Eigen::MatrixXcd data = getData_<std::complex<double>, 3>(fun);
110 addDataSet_(name + std::string("_real"), data.real());
111 addDataSet_(name + std::string("_imag"), data.imag());
112 return;
113 }
117 inline void addDataSet(const std::string& name,
118 std::function<double(const Eigen::Vector3d&)> fun) {
119 addDataSet_(name, getData_<double>(fun));
120 return;
121 }
125 inline void addDataSet(
126 const std::string& name,
127 std::function<std::complex<double>(const Eigen::Vector3d&)> fun) {
128 Eigen::VectorXcd data = getData_<std::complex<double>>(fun);
129 addDataSet_(name + std::string("_real"), data.real());
130 addDataSet_(name + std::string("_imag"), data.imag());
131 return;
132 }
137 template <typename LinOp>
138 inline void addDataSet(
139 const std::string& name, const AnsatzSpace<LinOp>& ansatz_space,
140 const Eigen::Matrix<typename LinearOperatorTraits<LinOp>::Scalar,
141 Eigen::Dynamic, Eigen::Dynamic>& coefficients) {
142 // Initialize FunctionEvaluator
144 evaluator.set_function(coefficients);
145
146 // Define function for FunctionEvaluator
147 typedef typename DifferentialFormTraits<
149 typename LinearOperatorTraits<LinOp>::Scalar>::FunctionSpaceValue
151 constexpr int dimension =
155 std::function<ReturnType(int, const Eigen::Vector2d&)> fun =
156 getEvaluatorFunction_<LinOp, dimension>::get(evaluator);
157
158 // Define function for FunctionEvaluator
160
161 return;
162 }
163
167 inline void writeToFile(const std::string& filename) {
168 std::ofstream output;
169 output.open(filename);
170 output << "<VTKFile type=\"PolyData\" version=\"0.1\" "
171 "byte_order=\"LittleEndian\">\n"
172 "<PolyData>\n"
173 "<Piece NumberOfPoints=\" "
174 << points.rows()
175 << "\" NumberOfVerts=\"0\" NumberOfLines=\"0\" NumberOfStrips=\"0\" "
176 "NumberOfPolys=\""
177 << cells.rows()
178 << "\">\n"
179 "<Points>\n"
180 "<DataArray type=\"Float32\" NumberOfComponents=\"3\" "
181 "format=\"ascii\">\n";
182 output << points;
183 output << "</DataArray>\n</Points>";
184 output << "<CellData Scalars=\"patch_number\" Normals=\"cell_normals\">\n"
185 "<DataArray type=\"Int32\" Name=\"patch_number\" "
186 "format=\"ascii\">\n";
187 output << patch_number;
188 output << "</DataArray>\n<DataArray type=\"Float32\" Name=\"cell_normals\" "
189 "NumberOfComponents=\"3\" format=\"ascii\">";
190 output << normals;
191 output << "</DataArray>\n";
192 for (auto data : additionalData) {
193 output << data;
194 }
195 output << "</CellData>\n"
196 "<Polys>\n"
197 "<DataArray type=\"Int32\" Name=\"connectivity\" "
198 "format=\"ascii\">\n";
199 output << cells;
200 output << "</DataArray>\n"
201 "<DataArray type=\"Int32\" Name=\"offsets\" "
202 "format=\"ascii\">\n";
203 for (int i = 0; i < cells.rows(); ++i) {
204 output << (i + 1) * 4;
205 output << "\n";
206 }
207 output << "</DataArray>\n"
208 "</Polys>\n"
209 "</Piece>\n"
210 "</PolyData>\n"
211 "</VTKFile>";
212 output.close();
213 return;
214 }
215 // can be used to clear the additional Data.
216 inline void clearData() {
217 additionalData = {};
218 additionalData.shrink_to_fit();
219 }
220
221 private:
222 // This routine turns the data of the above DataSet-routines into a string and
223 // stores it.
224 inline void addDataSet_(const std::string& name, const Eigen::MatrixXd& mat) {
225 assert(mat.cols() == 1 || mat.cols() == 3);
226 assert(mat.rows() == cells.rows());
227
228 const int cols = mat.cols();
229 std::string data_ascii = "<DataArray type=\"Float32\" Name=\"" + name +
230 "\" NumberOfComponents=\"" +
231 std::to_string(mat.cols()) +
232 "\" format=\"ascii\">\n";
233 std::ostringstream out;
234 out.precision(6);
235 for (int i = 0; i < mat.rows(); ++i) {
236 for (int j = 0; j < cols; ++j) {
237 out << std::scientific << mat(i, j);
238 data_ascii.append(std::move(out).str() + " ");
239 out.str("");
240 out.clear();
241 }
242 data_ascii.append("\n");
243 }
244 data_ascii.append("</DataArray>\n");
245 additionalData.push_back(data_ascii);
246 }
247
248 // generate data for functions living in spatial domains
249 template <typename Scalar, int dim>
250 inline Eigen::Matrix<Scalar, Eigen::Dynamic, dim> getData_(
251 const std::function<
252 Eigen::Matrix<Scalar, dim, 1>(const Eigen::Vector3d&)>& fun) {
253 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> data(cells.rows(),
254 dim);
255 int k = 0;
256 for (auto e = msh.get_element_tree().cpbegin();
257 e != msh.get_element_tree().cpend(); ++e) {
258 data.row(e->id_) =
259 fun(msh.get_geometry()[e->patch_].eval(e->referenceMidpoint()))
260 .transpose();
261 }
262 return data;
263 }
264 template <typename Scalar>
265 inline Eigen::Matrix<Scalar, Eigen::Dynamic, 1> getData_(
266 std::function<Scalar(const Eigen::Vector3d&)>& fun) {
267 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> data(cells.rows());
268 int k = 0;
269 for (auto e = msh.get_element_tree().cpbegin();
270 e != msh.get_element_tree().cpend(); ++e) {
271 data(e->id_) =
272 fun(msh.get_geometry()[e->patch_].eval(e->referenceMidpoint()));
273 }
274 return data;
275 }
276
277 // generate data for functions living on patches
278 template <typename Scalar, int dim>
279 inline Eigen::Matrix<Scalar, Eigen::Dynamic, dim> getData_(
280 const std::function<
281 Eigen::Matrix<Scalar, dim, 1>(int, const Eigen::Vector2d&)>& fun) {
282 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> data(cells.rows(),
283 dim);
284 int k = 0;
285 for (auto e = msh.get_element_tree().cpbegin();
286 e != msh.get_element_tree().cpend(); ++e) {
287 data.row(e->id_) = fun(e->patch_, e->referenceMidpoint()).transpose();
288 }
289 return data;
290 }
291 template <typename Scalar>
292 inline Eigen::Matrix<Scalar, Eigen::Dynamic, 1> getData_(
293 std::function<Scalar(int, const Eigen::Vector2d&)>& fun) {
294 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> data(cells.rows());
295 int k = 0;
296 for (auto e = msh.get_element_tree().cpbegin();
297 e != msh.get_element_tree().cpend(); ++e) {
298 data(e->id_) = fun(e->patch_, e->referenceMidpoint());
299 }
300 return data;
301 }
302
303 // helper function for FunctionEvaluator based output
304 // template <typename LinOp, typename ReturnType>
305 template <typename LinOp, int size>
306 struct getEvaluatorFunction_ {
307 static std::function<
308 Eigen::Matrix<typename LinearOperatorTraits<LinOp>::Scalar, size, 1>(
309 int, const Eigen::Vector2d&)>
310 get(const FunctionEvaluator<LinOp>& evaluator) {
311 typedef typename LinearOperatorTraits<LinOp>::Scalar Scalar;
312 typedef
313 typename Eigen::Matrix<typename LinearOperatorTraits<LinOp>::Scalar,
314 size, 1>
316 std::function<ReturnType(int, const Eigen::Vector2d&)> fun =
317 [&](int patch_number, const Eigen::Vector2d& reference_domain_point) {
318 return evaluator.evaluateOnPatch(patch_number,
320 };
321 return fun;
322 }
323 };
324 template <typename LinOp>
325 struct getEvaluatorFunction_<LinOp, 1> {
326 static std::function<typename LinearOperatorTraits<LinOp>::Scalar(
327 int, const Eigen::Vector2d&)>
328 get(const FunctionEvaluator<LinOp>& evaluator) {
329 typedef typename LinearOperatorTraits<LinOp>::Scalar Scalar;
330 std::function<typename DifferentialFormTraits<
331 LinearOperatorTraits<LinOp>::Form,
332 typename LinearOperatorTraits<LinOp>::Scalar>::
333 FunctionSpaceValue(int, const Eigen::Vector2d&)>
334 fun = [&](int patch_number,
335 const Eigen::Vector2d& reference_domain_point) {
336 return evaluator.evaluateOnPatch(patch_number,
338 };
339 return fun;
340 }
341 };
342
343 ClusterTree msh;
344 Eigen::MatrixXd points;
345 Eigen::MatrixXi cells;
346 Eigen::MatrixXd normals;
347 Eigen::VectorXi patch_number;
348 std::vector<std::string> additionalData;
349};
350
351} // namespace Bembel
352
353#endif // BEMBEL_SRC_IO_VTKSURFACEEXPORT_HPP_
The AnsatzSpace is the class that handles the assembly of the discrete basis.
void init_ClusterTree(const Geometry &geom, int M)
init
const PatchVector & get_geometry() const
Return const reference to the Geometry.
ElementTree & get_element_tree()
getter
ElementTreeNode::const_iterator cpbegin() const
Returns an iterator to the beginning of the sequence represented by the leafs as ElementTreeNodes of ...
ElementTreeNode::const_iterator cpend() const
Returns an iterator one past the end of the sequence represented by the leafs as ElementTreeNodes of ...
Eigen::MatrixXd generatePointList(Eigen::VectorXi *idct=nullptr) const
Return the coordinates of all points of the elements.
Eigen::MatrixXi generateElementList() const
Return list of elements containing the indices of the vertices.
The FunctionEvaluator provides means to evaluate coefficient vectors as functions on the geometry.
this class wraps a GeometryVector and provides some basic functionality, like reading Geometry files
Definition Geometry.hpp:20
Provides export routines from functions on geometries to the VTK file format.
void addDataSet(const std::string &name, std::function< Eigen::Vector3d(int, const Eigen::Vector2d &)> fun)
Add a function of the given type to the visualization.
void writeToFile(const std::string &filename)
Write geometry with passed visualization data to file.
void addDataSet(const std::string &name, std::function< std::complex< double >(const Eigen::Vector3d &)> fun)
Add a function of the given type to the visualization.
void addDataSet(const std::string &name, std::function< Eigen::Vector3cd(int, const Eigen::Vector2d &)> fun)
Add a function of the given type to the visualization.
void addDataSet(const std::string &name, const AnsatzSpace< LinOp > &ansatz_space, const Eigen::Matrix< typename LinearOperatorTraits< LinOp >::Scalar, Eigen::Dynamic, Eigen::Dynamic > &coefficients)
Add a function given through coefficients of an AnsatzSpace to the visualization.
VTKSurfaceExport(const Geometry &geo, int M)
void addDataSet(const std::string &name, std::function< Eigen::Vector3d(const Eigen::Vector3d &)> fun)
Add a function of the given type to the visualization.
void addDataSet(const std::string &name, std::function< Eigen::Vector3cd(const Eigen::Vector3d &)> fun)
Add a function of the given type to the visualization.
void addDataSet(const std::string &name, std::function< double(int, const Eigen::Vector2d &)> fun)
Add a function of the given type to the visualization.
void addDataSet(const std::string &name, std::function< double(const Eigen::Vector3d &)> fun)
Add a function of the given type to the visualization.
void addDataSet(const std::string &name, std::function< std::complex< double >(int, const Eigen::Vector2d &)> fun)
Add a function of the given type to the visualization.
Routines for the evalutation of pointwise errors.
constexpr int getFunctionSpaceOutputDimension()
struct containing specifications on DifferentialForms, i.e., the function spaces.
struct containing specifications on the linear operator has to be specialized or derived for any part...