109 const std::string& filepath,
110 const std::string& fileMode =
"") {
111 std::string actualFilepath = filepath;
112 std::string actualFileMode = fileMode;
115 if (actualFileMode.empty()) {
116 size_t dotPos = filepath.find_last_of(
'.');
117 if (dotPos != std::string::npos) {
118 std::string extension = filepath.substr(dotPos + 1);
119 if (extension ==
"txt" || extension ==
"bin") {
120 actualFileMode = extension;
122 actualFilepath = filepath;
125 actualFileMode =
"txt";
126 actualFilepath = filepath +
".txt";
130 actualFileMode =
"txt";
131 actualFilepath = filepath +
".txt";
135 if (filepath.find(
'.' + actualFileMode) != filepath.length() - actualFileMode.length() - 1) {
136 actualFilepath = filepath +
'.' + actualFileMode;
142 if (actualFileMode ==
"bin") {
143 file.open(actualFilepath, std::ios::binary);
144 if (!file.is_open()) {
145 std::cerr <<
"Error: Unable to open file for reading: " << actualFilepath << std::endl;
149 file.seekg(0, std::ios::end);
150 std::streamsize size = file.tellg();
151 file.seekg(0, std::ios::beg);
152 using value_type =
typename VectorContainer::value_type;
153 points.resize(size /
sizeof(value_type));
154 file.read(
reinterpret_cast<char*
>(points.data()), size);
156 }
else if (actualFileMode ==
"txt") {
157 file.open(actualFilepath);
158 if (!file.is_open()) {
159 std::cerr <<
"Error: Unable to open file for reading: " << actualFilepath << std::endl;
164 typename VectorContainer::value_type value;
165 while (file >> value) {
166 points.push_back(value);
170 std::cerr <<
"Error: Invalid file mode specified: " << actualFileMode << std::endl;
184inline std::vector<std::string>
select_folder(
const std::string& base_dir =
"output",
bool allow_all =
true) {
185 std::vector<std::string> epsilon_folders;
188 for (
const auto& entry : std::filesystem::directory_iterator(base_dir)) {
189 if (entry.is_directory()) {
190 std::string folder_name = entry.path().filename().string();
191 if (folder_name.find(
"epsilon_") == 0 || folder_name ==
"exact_sot") {
192 epsilon_folders.push_back(folder_name);
197 if (epsilon_folders.empty()) {
198 throw std::runtime_error(
"No epsilon or exact_sot folders found in " + base_dir);
202 std::sort(epsilon_folders.begin(), epsilon_folders.end());
205 std::cout <<
"\nAvailable folders:\n";
206 for (
size_t i = 0; i < epsilon_folders.size(); ++i) {
207 std::cout <<
"[" << i + 1 <<
"] " << epsilon_folders[i] <<
"\n";
210 std::cout <<
"[" << epsilon_folders.size() + 1 <<
"] ALL FOLDERS\n";
216 std::cout <<
"\nSelect a folder (1-" << (allow_all ? epsilon_folders.size() + 1 : epsilon_folders.size()) <<
"): ";
217 if (std::cin >> selection && selection >= 1 &&
218 selection <= (allow_all ? epsilon_folders.size() + 1 : epsilon_folders.size())) {
221 std::cout <<
"Invalid selection. Please try again.\n";
223 std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
'\n');
227 if (allow_all && selection == epsilon_folders.size() + 1) {
228 return epsilon_folders;
230 return {epsilon_folders[selection - 1]};
240 std::vector<std::pair<std::string, std::string>> files;
243 if (!std::filesystem::exists(dir)) {
244 throw std::runtime_error(
"Target point cloud hierarchy directory does not exist: " + dir);
248 for (
const auto& entry : std::filesystem::directory_iterator(dir)) {
249 if (entry.path().filename().string().find(
"level_") == 0 &&
250 entry.path().filename().string().find(
"_points.txt") != std::string::npos) {
251 std::string points_file = entry.path().string();
252 points_file = points_file.substr(0, points_file.length() - 4);
254 std::string level_num = points_file.substr(
255 points_file.find(
"level_") + 6,
256 points_file.find(
"_points") - points_file.find(
"level_") - 6
258 std::string density_file = dir +
"/level_" + level_num +
"_density";
260 if (std::filesystem::exists(density_file +
".txt")) {
261 files.push_back({points_file, density_file});
267 std::sort(files.begin(), files.end(), [](
const auto& a,
const auto& b) {
268 int level_a = std::stoi(a.first.substr(a.first.find(
"level_") + 6, 1));
269 int level_b = std::stoi(b.first.substr(b.first.find(
"level_") + 6, 1));
270 return level_a > level_b;
288 std::vector<std::vector<std::vector<size_t>>>& child_indices,
290 const MPI_Comm& mpi_communicator,
291 dealii::ConditionalOStream& pcout)
295 if (dealii::Utilities::MPI::this_mpi_process(mpi_communicator) == 0) {
297 std::string points_file = hierarchy_dir +
"/level_" + std::to_string(num_levels) +
"_points.txt";
298 if (!std::filesystem::exists(points_file)) {
305 num_levels = dealii::Utilities::MPI::broadcast(mpi_communicator, num_levels, 0);
307 if (num_levels == 0) {
308 pcout <<
"No hierarchy data found in " << hierarchy_dir << std::endl;
313 if (specific_level == -1) {
314 child_indices.resize(num_levels - 1);
318 if (specific_level >= num_levels - 1) {
322 if (
static_cast<int>(child_indices.size()) <= specific_level) {
323 child_indices.resize(num_levels - 1);
327 std::vector<std::vector<size_t>> level_data;
328 bool level_load_success =
true;
330 if (dealii::Utilities::MPI::this_mpi_process(mpi_communicator) == 0) {
331 std::string children_file = hierarchy_dir +
"/level_" + std::to_string(specific_level+1) +
"_children.txt";
332 std::ifstream children_in(children_file);
335 level_load_success =
false;
339 while (std::getline(children_in, line)) {
340 std::istringstream iss(line);
344 std::vector<size_t> children(num_children);
349 while (idx < num_children && iss >> child_idx) {
350 children[idx] = child_idx;
354 level_data.push_back(children);
360 level_load_success = dealii::Utilities::MPI::broadcast(mpi_communicator, level_load_success, 0);
362 if (!level_load_success) {
363 pcout <<
"Error loading hierarchy data at level " << specific_level << std::endl;
368 unsigned int n_parents = 0;
369 if (dealii::Utilities::MPI::this_mpi_process(mpi_communicator) == 0) {
370 n_parents = level_data.size();
372 n_parents = dealii::Utilities::MPI::broadcast(mpi_communicator, n_parents, 0);
374 if (dealii::Utilities::MPI::this_mpi_process(mpi_communicator) != 0) {
375 level_data.resize(n_parents);
378 for (
unsigned int i = 0; i < n_parents; ++i) {
379 unsigned int n_children = 0;
380 if (dealii::Utilities::MPI::this_mpi_process(mpi_communicator) == 0) {
381 n_children = level_data[i].size();
383 n_children = dealii::Utilities::MPI::broadcast(mpi_communicator, n_children, 0);
385 if (dealii::Utilities::MPI::this_mpi_process(mpi_communicator) != 0) {
386 level_data[i].resize(n_children);
390 MPI_Bcast(&level_data[i][0], n_children, MPI_UNSIGNED_LONG, 0, mpi_communicator);
394 child_indices[specific_level] = level_data;
410bool write_mesh(
const dealii::Triangulation<dim, spacedim>& mesh,
411 const std::string& filepath,
412 const std::vector<std::string>& formats,
413 const std::vector<double>* cell_data =
nullptr,
414 const std::string& data_name =
"cell_data")
417 std::filesystem::path path(filepath);
418 std::filesystem::create_directories(path.parent_path());
420 dealii::GridOut grid_out;
422 for (
const auto& format : formats) {
423 if (format ==
"vtk") {
424 std::ofstream out_vtk(filepath +
".vtk");
425 if (!out_vtk.is_open()) {
426 std::cerr <<
"Error: Unable to open file for writing: "
427 << filepath +
".vtk" << std::endl;
430 grid_out.write_vtk(mesh, out_vtk);
431 std::cout <<
"Mesh saved to: " << filepath +
".vtk" << std::endl;
433 else if (format ==
"msh") {
435 std::ofstream out_msh(filepath +
".msh");
436 if (!out_msh.is_open()) {
437 std::cerr <<
"Error: Unable to open file for writing: "
438 << filepath +
".msh" << std::endl;
441 grid_out.write_msh(mesh, out_msh);
445 std::string cmd =
"gmsh " + filepath +
".msh -format msh2 -save_all -3 -o " +
446 filepath +
"_msh2.msh && mv " + filepath +
"_msh2.msh " +
448 int ret = system(cmd.c_str());
450 std::cerr <<
"Error: Failed to convert mesh to MSH2 format" << std::endl;
453 std::cout <<
"Mesh saved and converted to MSH2 format: " << filepath +
".msh" << std::endl;
455 else if (format ==
"vtu") {
456 dealii::DataOut<dim, spacedim> data_out;
457 data_out.attach_triangulation(mesh);
460 if (cell_data !=
nullptr) {
461 Assert(cell_data->size() == mesh.n_active_cells(),
462 dealii::ExcDimensionMismatch(cell_data->size(),
463 mesh.n_active_cells()));
465 dealii::Vector<double> cell_data_vector(cell_data->begin(), cell_data->end());
466 data_out.add_data_vector(cell_data_vector, data_name);
469 data_out.build_patches();
471 std::ofstream out_vtu(filepath +
".vtu");
472 if (!out_vtu.is_open()) {
473 std::cerr <<
"Error: Unable to open file for writing: "
474 << filepath +
".vtu" << std::endl;
477 data_out.write_vtu(out_vtu);
478 std::cout <<
"Mesh saved to: " << filepath +
".vtu" << std::endl;
481 std::cerr <<
"Warning: Unsupported format '" << format
482 <<
"' requested" << std::endl;
488 catch (
const std::exception& e) {
489 std::cerr <<
"Error writing mesh: " << e.what() << std::endl;
505 const dealii::DoFHandler<dim, spacedim> &source_dh,
506 const dealii::Vector<double> &source_field,
507 const dealii::DoFHandler<dim, spacedim> &target_dh,
508 dealii::LinearAlgebra::distributed::Vector<double> &target_field)
510 using namespace dealii;
512 Assert(source_field.size() == source_dh.n_dofs(),
513 ExcDimensionMismatch(source_field.size(), source_dh.n_dofs()));
514 Assert(target_field.size() == target_dh.n_dofs(),
515 ExcDimensionMismatch(target_field.size(), target_dh.n_dofs()));
517 const auto &source_fe = source_dh.get_fe();
518 const auto &target_fe = target_dh.get_fe();
520 std::unique_ptr<Mapping<dim, spacedim>> source_mapping;
521 if (source_fe.reference_cell() == ReferenceCells::get_hypercube<dim>())
522 source_mapping = std::make_unique<MappingQ1<dim, spacedim>>();
524 source_mapping = std::make_unique<MappingFE<dim, spacedim>>(FE_SimplexP<dim, spacedim>(1));
526 std::unique_ptr<Mapping<dim, spacedim>> target_mapping;
527 if (target_fe.reference_cell() == ReferenceCells::get_hypercube<dim>())
528 target_mapping = std::make_unique<MappingQ1<dim, spacedim>>();
530 target_mapping = std::make_unique<MappingFE<dim, spacedim>>(FE_SimplexP<dim, spacedim>(1));
532 const Quadrature<dim> target_quadrature(target_fe.get_generalized_support_points());
533 FEValues<dim, spacedim> target_fe_values(*target_mapping,
536 update_quadrature_points);
538 std::vector<types::global_dof_index> source_dof_indices(source_fe.n_dofs_per_cell());
539 std::vector<types::global_dof_index> target_dof_indices(target_fe.n_dofs_per_cell());
540 Vector<double> source_cell_values(source_fe.n_dofs_per_cell());
542 Vector<double> target_values(target_field.size());
543 Vector<double> weights(target_field.size());
545 std::vector<std::pair<Point<spacedim>,
typename DoFHandler<dim, spacedim>::active_cell_iterator>> cell_centers;
546 for (
const auto &cell : source_dh.active_cell_iterators())
548 if (!cell->is_locally_owned())
550 cell_centers.emplace_back(cell->center(), cell);
553 std::vector<std::pair<Point<spacedim>,
unsigned int>> indexed_points;
554 indexed_points.reserve(cell_centers.size());
555 for (
unsigned int i = 0; i < cell_centers.size(); ++i)
556 indexed_points.emplace_back(cell_centers[i].first, i);
558 using RTreeParams = boost::geometry::index::rstar<8>;
559 boost::geometry::index::rtree<std::pair<Point<spacedim>,
unsigned int>, RTreeParams>
560 rtree(indexed_points.begin(), indexed_points.end());
562 for (
const auto &target_cell : target_dh.active_cell_iterators())
564 if (!target_cell->is_locally_owned())
567 target_fe_values.reinit(target_cell);
568 const std::vector<Point<spacedim>> &target_points = target_fe_values.get_quadrature_points();
569 target_cell->get_dof_indices(target_dof_indices);
571 for (
unsigned int q = 0; q < target_points.size(); ++q)
573 const Point<spacedim> &target_point = target_points[q];
575 std::vector<std::pair<Point<spacedim>,
unsigned int>> nearest;
576 rtree.query(boost::geometry::index::nearest(target_point, 1), std::back_inserter(nearest));
581 const unsigned int nearest_index = nearest.front().second;
582 auto chosen_source_cell = cell_centers[nearest_index].second;
587 p_unit = source_mapping->transform_real_to_unit_cell(chosen_source_cell, target_point);
594 chosen_source_cell->get_dof_indices(source_dof_indices);
595 for (
unsigned int i = 0; i < source_dof_indices.size(); ++i)
596 source_cell_values[i] = source_field[source_dof_indices[i]];
598 double source_value = 0.0;
599 for (
unsigned int i = 0; i < source_fe.n_dofs_per_cell(); ++i)
600 source_value += source_cell_values[i] * source_fe.shape_value(i, p_unit);
602 const unsigned int target_dof = target_dof_indices[q];
603 target_values[target_dof] += source_value;
604 weights[target_dof] += 1.0;
608 for (types::global_dof_index i = 0; i < target_field.size(); ++i)
610 target_field[i] = target_values[i] / weights[i];
612 target_field.compress(VectorOperation::insert);
626 const dealii::Vector<double> &source_field,
627 const dealii::DoFHandler<dim, spacedim> &target_dh,
628 dealii::LinearAlgebra::distributed::Vector<double> &target_field)
630 using namespace dealii;
632 Assert(source_field.size() == source_dh.n_dofs(),
633 ExcDimensionMismatch(source_field.size(), source_dh.n_dofs()));
634 Assert(target_field.size() == target_dh.n_dofs(),
635 ExcDimensionMismatch(target_field.size(), target_dh.n_dofs()));
637 const auto &source_fe = source_dh.get_fe();
638 const auto &target_fe = target_dh.get_fe();
640 std::unique_ptr<Mapping<dim, spacedim>> source_mapping;
641 if (source_dh.get_fe().reference_cell() == ReferenceCells::get_hypercube<dim>())
642 source_mapping = std::make_unique<MappingQ1<dim, spacedim>>();
644 source_mapping = std::make_unique<MappingFE<dim, spacedim>>(FE_SimplexP<dim, spacedim>(1));
646 std::unique_ptr<Mapping<dim, spacedim>> target_mapping;
647 if (target_dh.get_fe().reference_cell() == ReferenceCells::get_hypercube<dim>())
648 target_mapping = std::make_unique<MappingQ1<dim, spacedim>>();
650 target_mapping = std::make_unique<MappingFE<dim, spacedim>>(FE_SimplexP<dim, spacedim>(1));
652 std::vector<std::pair<Point<spacedim>,
typename DoFHandler<dim, spacedim>::active_cell_iterator>>
655 for (
const auto &cell : source_dh.active_cell_iterators())
657 if (!cell->is_locally_owned())
659 cell_centers.emplace_back(cell->center(), cell);
662 std::vector<std::pair<Point<spacedim>,
unsigned int>> indexed_points;
663 indexed_points.reserve(cell_centers.size());
664 for (
unsigned int i = 0; i < cell_centers.size(); ++i)
665 indexed_points.emplace_back(cell_centers[i].first, i);
667 using RTreeParams = boost::geometry::index::rstar<8>;
668 boost::geometry::index::rtree<std::pair<Point<spacedim>,
unsigned int>, RTreeParams>
669 rtree(indexed_points.begin(), indexed_points.end());
671 const Quadrature<dim> quadrature(target_fe.get_unit_support_points());
673 FEValues<dim> source_fe_values(*source_mapping,
676 update_values | update_quadrature_points);
678 FEValues<dim> target_fe_values(*target_mapping,
681 update_quadrature_points);
683 std::vector<types::global_dof_index> source_dof_indices(source_fe.n_dofs_per_cell());
684 std::vector<types::global_dof_index> target_dof_indices(target_fe.n_dofs_per_cell());
685 Vector<double> source_cell_values(source_fe.n_dofs_per_cell());
687 Vector<double> target_values(target_dh.n_dofs());
688 Vector<double> weights(target_dh.n_dofs());
690 for (
const auto &target_cell : target_dh.active_cell_iterators())
692 if (!target_cell->is_locally_owned())
695 target_fe_values.reinit(target_cell);
696 const std::vector<Point<spacedim>> &target_points = target_fe_values.get_quadrature_points();
697 target_cell->get_dof_indices(target_dof_indices);
699 for (
unsigned int q = 0; q < target_points.size(); ++q)
701 const Point<spacedim> &target_point = target_points[q];
703 std::vector<std::pair<Point<spacedim>,
unsigned int>> nearest;
704 rtree.query(boost::geometry::index::nearest(target_point, 1),
705 std::back_inserter(nearest));
707 Assert(!nearest.empty(), ExcInternalError(
"RTree nearest neighbor search failed"));
709 const auto &source_cell = cell_centers[nearest[0].second].second;
711 source_fe_values.reinit(source_cell);
712 source_cell->get_dof_indices(source_dof_indices);
714 for (
unsigned int i = 0; i < source_dof_indices.size(); ++i)
715 source_cell_values[i] = source_field[source_dof_indices[i]];
717 double source_value = 0;
718 for (
unsigned int i = 0; i < source_fe.n_dofs_per_cell(); ++i)
719 source_value += source_cell_values[i] * source_fe_values.shape_value(i, q);
721 const unsigned int target_dof = target_dof_indices[q];
722 target_values[target_dof] += source_value;
723 weights[target_dof] += 1.0;
727 for (types::global_dof_index i = 0; i < target_dh.n_dofs(); ++i)
729 target_field[i] = target_values[i] / weights[i];
731 target_field.compress(VectorOperation::insert);
779 const dealii::Triangulation<dim, spacedim>& triangulation,
780 const unsigned int fe_degree = 1,
781 const unsigned int mapping_degree = 1)
783 bool has_quads_or_hexes =
false;
784 bool has_triangles_or_tets =
false;
786 for (
const auto& cell : triangulation.active_cell_iterators()) {
787 if (cell->reference_cell() == dealii::ReferenceCells::get_hypercube<dim>())
788 has_quads_or_hexes =
true;
789 if (cell->reference_cell() == dealii::ReferenceCells::get_simplex<dim>())
790 has_triangles_or_tets =
true;
793 std::unique_ptr<dealii::FiniteElement<dim, spacedim>> fe;
794 std::unique_ptr<dealii::Mapping<dim, spacedim>> mapping;
796 if (has_triangles_or_tets) {
797 fe = std::make_unique<dealii::FE_SimplexP<dim, spacedim>>(fe_degree);
798 mapping = std::make_unique<dealii::MappingFE<dim, spacedim>>(dealii::FE_SimplexP<dim, spacedim>(mapping_degree));
799 }
else if (has_quads_or_hexes) {
800 fe = std::make_unique<dealii::FE_Q<dim, spacedim>>(fe_degree);
801 mapping = std::make_unique<dealii::MappingQ1<dim, spacedim>>();
803 throw std::runtime_error(
"Could not determine mesh cell type in triangulation");
806 return {std::move(fe), std::move(mapping)};
853 const std::vector<dealii::Point<spacedim>>& points,
854 const std::vector<double>& density,
855 const std::string& filename,
856 const std::string& description =
"Points with density values",
857 const std::string& density_name =
"density")
859 if (points.size() != density.size()) {
860 std::cerr <<
"Error: Points and density vectors must have the same size" << std::endl;
864 if (points.empty()) {
865 std::cerr <<
"Error: Cannot write empty point set" << std::endl;
870 std::filesystem::path path(filename);
871 std::filesystem::create_directories(path.parent_path());
873 std::ofstream vtk_file(filename);
874 if (!vtk_file.is_open()) {
875 std::cerr <<
"Error: Unable to open file for writing: " << filename << std::endl;
880 vtk_file <<
"# vtk DataFile Version 3.0\n"
881 << description <<
"\n"
883 <<
"DATASET UNSTRUCTURED_GRID\n"
884 <<
"POINTS " << points.size() <<
" double\n";
887 for (
const auto& p : points) {
888 vtk_file << p[0] <<
" " << p[1];
890 vtk_file <<
" " << p[2];
891 }
else if (spacedim == 2) {
898 const unsigned int n_points = points.size();
899 vtk_file <<
"CELLS " << n_points <<
" " << 2 * n_points <<
"\n";
900 for (
unsigned int i = 0; i < n_points; ++i) {
901 vtk_file <<
"1 " << i <<
"\n";
905 vtk_file <<
"CELL_TYPES " << n_points <<
"\n";
906 for (
unsigned int i = 0; i < n_points; ++i) {
911 vtk_file <<
"POINT_DATA " << n_points <<
"\n"
912 <<
"SCALARS " << density_name <<
" double 1\n"
913 <<
"LOOKUP_TABLE default\n";
914 for (std::size_t i = 0; i < n_points; ++i) {
915 vtk_file << density[i] <<
"\n";
920 std::cout <<
"Points with density saved to: " << filename << std::endl;
937 const std::vector<dealii::Point<spacedim>>& source_points,
938 const std::vector<dealii::Point<spacedim>>& mapped_points,
939 const std::vector<double>& density,
940 const std::string& filename,
941 const std::string& description =
"Points with displacement vectors",
942 const std::string& density_name =
"density")
944 if (source_points.size() != mapped_points.size() ||
945 source_points.size() != density.size()) {
946 std::cerr <<
"Error: Source points, mapped points, and density vectors must have the same size" << std::endl;
950 if (source_points.empty()) {
951 std::cerr <<
"Error: Cannot write empty point set" << std::endl;
956 std::filesystem::path path(filename);
957 std::filesystem::create_directories(path.parent_path());
959 std::ofstream vtk_file(filename);
960 if (!vtk_file.is_open()) {
961 std::cerr <<
"Error: Unable to open file for writing: " << filename << std::endl;
966 vtk_file <<
"# vtk DataFile Version 3.0\n"
967 << description <<
"\n"
969 <<
"DATASET UNSTRUCTURED_GRID\n"
970 <<
"POINTS " << source_points.size() <<
" double\n";
973 for (
const auto& p : source_points) {
974 vtk_file << p[0] <<
" " << p[1];
976 vtk_file <<
" " << p[2];
977 }
else if (spacedim == 2) {
984 const unsigned int n_points = source_points.size();
985 vtk_file <<
"CELLS " << n_points <<
" " << 2 * n_points <<
"\n";
986 for (
unsigned int i = 0; i < n_points; ++i) {
987 vtk_file <<
"1 " << i <<
"\n";
991 vtk_file <<
"CELL_TYPES " << n_points <<
"\n";
992 for (
unsigned int i = 0; i < n_points; ++i) {
997 vtk_file <<
"POINT_DATA " << n_points <<
"\n";
1000 vtk_file <<
"VECTORS displacement double\n";
1001 for (std::size_t i = 0; i < n_points; ++i) {
1002 dealii::Tensor<1, spacedim> displacement = mapped_points[i] - source_points[i];
1003 vtk_file << displacement[0] <<
" " << displacement[1];
1004 if (spacedim == 3) {
1005 vtk_file <<
" " << displacement[2];
1006 }
else if (spacedim == 2) {
1013 vtk_file <<
"SCALARS " << density_name <<
" double 1\n"
1014 <<
"LOOKUP_TABLE default\n";
1015 for (std::size_t i = 0; i < n_points; ++i) {
1016 vtk_file << density[i] <<
"\n";
1021 std::cout <<
"Points with displacement and density saved to: " << filename << std::endl;
1040 const std::string& filename,
1041 dealii::DoFHandler<dim, spacedim>& vtk_dof_handler,
1042 dealii::Vector<double>& vtk_field,
1043 dealii::Triangulation<dim, spacedim>& vtk_tria,
1044 const MPI_Comm& mpi_communicator,
1045 dealii::ConditionalOStream& pcout,
1046 bool broadcast_field =
false,
1047 const std::string& field_name =
"normalized_density")
1049 bool success =
false;
1054 dealii::GridIn<dim, spacedim> grid_in;
1055 grid_in.attach_triangulation(vtk_tria);
1057 std::ifstream vtk_file(filename);
1060 <<
"Error: Could not open VTK file: " << filename
1066 grid_in.read_vtk(vtk_file);
1067 pcout <<
"VTK mesh: " << vtk_tria.n_active_cells() <<
" cells" << std::endl;
1073 vtk_dof_handler.clear();
1074 vtk_dof_handler.reinit(vtk_tria);
1075 vtk_dof_handler.distribute_dofs(*fe);
1078 vtk_field.reinit(vtk_dof_handler.n_dofs());
1081 if (dealii::Utilities::MPI::this_mpi_process(mpi_communicator) == 0) {
1084 std::ifstream vtk_reader(filename);
1086 bool found_point_data =
false;
1087 bool found_scalars =
false;
1088 std::string found_field_name;
1090 while (std::getline(vtk_reader, line)) {
1091 if (line.find(
"POINT_DATA") != std::string::npos) {
1092 found_point_data =
true;
1095 if (found_point_data && line.find(
"SCALARS") != std::string::npos) {
1096 std::istringstream iss(line);
1098 iss >> dummy >> found_field_name;
1101 if (found_field_name == field_name) {
1102 found_scalars =
true;
1103 pcout <<
"Found scalar field: " << found_field_name << std::endl;
1106 std::getline(vtk_reader, line);
1109 for (
unsigned int i = 0; i < vtk_dof_handler.n_dofs(); ++i) {
1110 if (!(vtk_reader >> vtk_field[i])) {
1112 <<
"Error reading scalar field data from VTK"
1114 found_scalars =
false;
1123 success = found_scalars;
1126 <<
"Error: Could not find scalar field '" << field_name <<
"' in VTK file"
1129 }
catch (
const std::exception& e) {
1131 <<
"Exception during VTK file reading: " << e.what()
1137 if (broadcast_field) {
1138 success = dealii::Utilities::MPI::broadcast(mpi_communicator, success, 0);
1141 vtk_field = dealii::Utilities::MPI::broadcast(mpi_communicator, vtk_field, 0);